Permalink
Browse files

Fixed most resolving of mixins and variables for issue #1 (still some…

… problems with Scss imports).
  • Loading branch information...
ronniekk committed Apr 11, 2012
1 parent b7a7b81 commit dbd0b7d82cd7a07450553c56b151496f0557e351
View
@@ -269,5 +269,6 @@
<extensions defaultExtensionNs="com.intellij">
<projectConfigurable id="com.github.cssxfire.ProjectSettingsConfigurable" implementation="com.github.cssxfire.ProjectSettingsConfigurable"/>
+ <gotoDeclarationHandler id="com.github.cssxfire.resolve.GotoDeclarationProvider" implementation="com.github.cssxfire.resolve.GotoDeclarationResolver"/>
</extensions>
</idea-plugin>
@@ -16,8 +16,7 @@
package com.github.cssxfire;
-import com.github.cssxfire.resolve.CssRulesetReference;
-import com.github.cssxfire.resolve.CssXFireReferenceProvider;
+import com.github.cssxfire.resolve.GotoDeclarationResolver;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.lang.css.CSSLanguage;
@@ -27,7 +26,9 @@
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.css.*;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.PsiSearchHelper;
@@ -37,8 +38,6 @@
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
/**
* Created by IntelliJ IDEA.
@@ -120,65 +119,29 @@ public static boolean processParents(@NotNull PsiElement element, @NotNull PsiEl
return true;
}
- /**
- * Recursion guard
- */
- private static ThreadLocal<Set<PsiElement>> processed = new ThreadLocal<Set<PsiElement>>() {
- @Override
- protected Set<PsiElement> initialValue() {
- return new HashSet<PsiElement>();
- }
- };
-
@Nullable
- public static CssTermList resolveVariableAssignment(@NotNull CssDeclaration cssDeclaration) {
+ public static PsiElement resolveVariableAssignment(@NotNull CssDeclaration cssDeclaration) {
CssTermList termList = PsiTreeUtil.getChildOfType(cssDeclaration, CssTermList.class);
- try {
- CssTermList result = null;
- while (termList != null) {
- if (!processed.get().add(termList)) {
- return null; // infinite recursion detected
- }
- CssTerm[] terms = PsiTreeUtil.getChildrenOfType(termList, CssTerm.class);
- if (terms == null || terms.length != 1) {
- return null; // not an explicit variable reference
- }
- termList = resolveTermList(termList);
- if (termList == null) {
- return result;
- }
- result = termList;
- }
- return result;
- } finally {
- processed.get().clear();
+ if (termList == null) {
+ return null;
+ }
+ CssTerm[] terms = PsiTreeUtil.getChildrenOfType(termList, CssTerm.class);
+ if (terms == null || terms.length != 1) {
+ return null; // not an explicit variable reference
}
- }
- @Nullable
- private static CssTermList resolveTermList(@NotNull CssTermList termList) {
- final Ref<CssTermList> result = new Ref<CssTermList>(null);
- PsiTreeUtil.processElements(termList, new PsiElementProcessor() {
- public boolean execute(@NotNull PsiElement psiElement) {
- if (psiElement instanceof CssTerm) {
- return true; // CssIdentifierReference - skip
- }
- for (PsiReference reference : psiElement.getReferences()) {
- PsiElement referenced = reference.resolve();
- if (referenced != null) {
- for (PsiElement child : referenced.getChildren()) {
- if (child instanceof CssTermList) {
- result.set((CssTermList) child);
- return false;
- }
- }
- }
+ final Ref<PsiElement> resolved = new Ref<PsiElement>(null);
+ PsiTreeUtil.processElements(terms[0], new PsiElementProcessor() {
+ public boolean execute(@NotNull PsiElement element) {
+ PsiElement[] targets = GotoDeclarationResolver.INSTANCE.getGotoDeclarationTargets(element, null);
+ if (targets != null && targets.length == 1) {
+ resolved.set(targets[0]);
+ return false;
}
return true;
}
});
-
- return result.get();
+ return resolved.get();
}
public static boolean processCssDeclarations(@Nullable CssBlock block, final PsiElementProcessor<CssDeclaration> declarationProcessor) {
@@ -196,21 +159,12 @@ public static boolean processCssDeclarations(@Nullable CssBlock block, final Psi
if (isDynamicCssLanguage(block) && ProjectSettings.getInstance(block.getProject()).isResolveMixins()) {
return PsiTreeUtil.processElements(block, new PsiElementProcessor() {
public boolean execute(@NotNull PsiElement element) {
- PsiReference[] references = getFromElementAndMyProviders(element);
- for (PsiReference reference : references) {
- if (reference instanceof CssRulesetReference) {
- PsiElement resolved = reference.resolve();
- if (resolved instanceof CssRuleset) {
- if (!processCssDeclarations(((CssRuleset) resolved).getBlock(), declarationProcessor)) {
- return false;
- }
- }
- } else if (reference != null && "org.jetbrains.plugins.scss.references.SCSSMixinReference".equals(reference.getClass().getName())) {
- PsiElement resolved = reference.resolve();
- if (resolved != null) {
- if (!processCssDeclarations(PsiTreeUtil.getChildOfType(resolved, CssBlock.class), declarationProcessor)) {
- return false;
- }
+ PsiElement[] targets = GotoDeclarationResolver.INSTANCE.getGotoDeclarationTargets(element, null);
+ if (targets != null && targets.length == 1) {
+ PsiElement resolved = targets[0];
+ if (resolved instanceof CssRuleset) {
+ if (!processCssDeclarations(((CssRuleset) resolved).getBlock(), declarationProcessor)) {
+ return false;
}
}
}
@@ -221,23 +175,6 @@ public boolean execute(@NotNull PsiElement element) {
return true;
}
- private static PsiReference[] getFromElementAndMyProviders(@NotNull PsiElement element) {
- PsiReference[] original = element.getReferences();
- PsiReference[] extras = CssXFireReferenceProvider.getReferencesByElement(element);
- if (original.length == 0) {
- return extras;
- }
- if (extras.length == 0) {
- return original;
- }
-
- PsiReference[] all = new PsiReference[original.length + extras.length];
- System.arraycopy(original, 0, all, 0, original.length);
- System.arraycopy(extras, 0, all, original.length, extras.length);
-
- return all;
- }
-
/**
* Checks if the element is contained in a Less or Sass language file
*
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012 Ronnie Kolehmainen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.cssxfire.resolve;
+
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: Ronnie
+ */
+public class CssPluginsFacade {
+ private static final FileType LESS_FILE_TYPE = FileTypeManager.getInstance().getStdFileType("LESS");
+ private static final FileType SASS_FILE_TYPE = FileTypeManager.getInstance().getStdFileType("SASS");
+ private static final FileType SCSS_FILE_TYPE = FileTypeManager.getInstance().getStdFileType("SCSS");
+ private static final CssResolveProcessor NOP_PROCESSOR = new CssResolveProcessor(null) {
+ @Override
+ public boolean executeInternal(@NotNull PsiElement element) {
+ return false;
+ }
+ };
+
+ @NotNull
+ public static CssResolveProcessor getVariableProcessor(@NotNull PsiElement element, String name) {
+ return createResolveProcessor(element, name, "Variable");
+ }
+
+ @NotNull
+ public static CssResolveProcessor getMixinProcessor(@NotNull PsiElement element, String name) {
+ return createResolveProcessor(element, name, "Mixin");
+ }
+
+ @NotNull
+ private static CssResolveProcessor createResolveProcessor(@NotNull PsiElement element, String name, String type) {
+ PsiFile file = element.getContainingFile();
+ if (file == null) {
+ return NOP_PROCESSOR;
+ }
+
+ FileType fileType = file.getFileType();
+ if (fileType == PlainTextFileType.INSTANCE) {
+ return NOP_PROCESSOR;
+ }
+
+ String prefix = null;
+ if (fileType == LESS_FILE_TYPE) {
+ prefix = "Less";
+ } else if (fileType == SCSS_FILE_TYPE) {
+ prefix = "Scss";
+ }
+
+ if (prefix != null) {
+ try {
+ Class<? extends CssResolveProcessor> clazz = (Class<? extends CssResolveProcessor>) Class.forName(CssPluginsFacade.class.getPackage().getName() + "." + prefix + type + "Processor");
+ Constructor<? extends CssResolveProcessor> constructor = clazz.getConstructor(String.class);
+ return constructor.newInstance(name);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ return NOP_PROCESSOR;
+ }
+}
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012 Ronnie Kolehmainen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.cssxfire.resolve;
+
+import com.intellij.openapi.util.Ref;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.css.CssImport;
+import com.intellij.psi.search.PsiElementProcessor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: Ronnie
+ */
+public abstract class CssResolveProcessor implements PsiElementProcessor {
+ protected final String name;
+ protected final Ref<PsiElement> result = new Ref<PsiElement>(null);
+ private final Set<CssImport> imports = new HashSet<CssImport>();
+
+ protected CssResolveProcessor(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Nullable
+ public PsiElement getResult() {
+ return result.get();
+ }
+
+ @Nullable
+ public synchronized CssImport popImport() {
+ if (imports.isEmpty()) {
+ return null;
+ }
+ Iterator<CssImport> iterator = imports.iterator();
+ CssImport next = iterator.next();
+ iterator.remove();
+ return next;
+ }
+
+ public boolean executeInScope(@NotNull PsiElement base) {
+ return true;
+ }
+
+ public abstract boolean executeInternal(@NotNull PsiElement element);
+
+ public boolean execute(@NotNull PsiElement element) {
+ if (element instanceof CssImport) {
+ CssImport cssImport = (CssImport) element;
+ imports.add(cssImport);
+ return true;
+ }
+ return executeInternal(element);
+ }
+}
Oops, something went wrong.

0 comments on commit dbd0b7d

Please sign in to comment.