package com.sylvanaar.idea.Lua.lang.psi.resolve; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiManager; import com.intellij.psi.ResolveState; import com.intellij.psi.impl.source.resolve.ResolveCache; import com.intellij.psi.search.GlobalSearchScope; import com.sylvanaar.idea.Lua.lang.psi.LuaPsiFile; import com.sylvanaar.idea.Lua.lang.psi.LuaReferenceElement; import com.sylvanaar.idea.Lua.lang.psi.expressions.LuaDeclarationExpression; import com.sylvanaar.idea.Lua.lang.psi.expressions.LuaExpression; import com.sylvanaar.idea.Lua.lang.psi.impl.statements.LuaFunctionDefinitionStatementImpl; import com.sylvanaar.idea.Lua.lang.psi.resolve.processors.ResolveProcessor; import com.sylvanaar.idea.Lua.lang.psi.resolve.processors.SymbolResolveProcessor; import com.sylvanaar.idea.Lua.lang.psi.statements.LuaLocalDefinitionStatement; import com.sylvanaar.idea.Lua.lang.psi.stubs.index.LuaGlobalDeclarationIndex; import com.sylvanaar.idea.Lua.lang.psi.symbols.LuaLocal; import com.sylvanaar.idea.Lua.lang.psi.symbols.LuaSymbol; import com.sylvanaar.idea.Lua.options.LuaApplicationSettings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; public class LuaResolver implements ResolveCache.PolyVariantResolver<LuaReferenceElement> { public static final Logger log = Logger.getInstance("Lua.LuaResolver"); boolean ignoreAliasing = false; public void setIgnoreAliasing(boolean b) { ignoreAliasing=b; } public boolean getIgnoreAliasing() { return ignoreAliasing; } static Collection<LuaDeclarationExpression> filteredGlobalsCache = null; @Nullable public LuaResolveResult[] resolve(LuaReferenceElement reference, boolean incompleteCode) { if (reference.getText() == null) return LuaResolveResult.EMPTY_ARRAY; final LuaResolveResult[] results = _resolve(reference, reference.getManager(), incompleteCode, ignoreAliasing); return results; } private static LuaResolveResult[] _resolve(LuaReferenceElement ref, PsiManager manager, boolean incompleteCode, boolean ignoreAliasing) { PsiElement element = ref.getElement(); String prefix = null, postfix = null; LuaResolveResult[] selfResolves = null; if (element.getText().startsWith("self.") || element.getText().startsWith("self:")) { postfix = element.getText().substring(5); prefix = findSelfPrefix(element); ResolveProcessor processor = new SymbolResolveProcessor(prefix + postfix, ref, incompleteCode); ResolveUtil.treeWalkUp(ref, processor); if (processor.hasCandidates()) { selfResolves = processor.getCandidates(); } } final String refName = ref.getName(); if (refName == null) { return LuaResolveResult.EMPTY_ARRAY; } ResolveProcessor processor = new SymbolResolveProcessor(refName, ref, incompleteCode); if (selfResolves != null) for(LuaResolveResult result : selfResolves) processor.addCandidate(result); ResolveUtil.treeWalkUp(ref, processor); if (/*processor.hasCandidates() || */ref.getElement() instanceof LuaLocal) { if (!processor.hasCandidates()) return LuaResolveResult.EMPTY_ARRAY; return new LuaResolveResult[]{processor.getCandidates()[0]}; } // Search the Project Files final Project project = manager.getProject(); final GlobalSearchScope sc = ref.getResolveScope(); final LuaPsiFile currentFile = (LuaPsiFile) ref.getContainingFile(); LuaGlobalDeclarationIndex index = LuaGlobalDeclarationIndex.getInstance(); Collection<LuaDeclarationExpression> names = index.get(refName, project, sc); for (LuaDeclarationExpression name : names) { name.processDeclarations(processor, ResolveState.initial(), ref, ref); } if (processor.hasCandidates()) { return processor.getCandidates(); } return LuaResolveResult.EMPTY_ARRAY; } private static String findSelfPrefix(PsiElement element) { while (!(element instanceof LuaFunctionDefinitionStatementImpl) && element != null) element = element.getContext(); // Must be inside a function if (element == null) return null; LuaFunctionDefinitionStatementImpl func = (LuaFunctionDefinitionStatementImpl) element; LuaSymbol symbol = func.getIdentifier(); int colonIdx = symbol.getText().lastIndexOf(':'); int dotIdx = symbol.getText().lastIndexOf('.'); if (colonIdx < 0 && dotIdx < 0) return null; int idx = Math.max(colonIdx, dotIdx); String prefix = symbol.getText().substring(0, idx + 1); return prefix; } public static LuaReferenceElement resolveAlias(LuaReferenceElement ref, @NotNull PsiElement resolved) { if (!LuaApplicationSettings.getInstance().RESOLVE_ALIASED_IDENTIFIERS) return null; if (resolved instanceof LuaLocal && resolved.getContext().getContext() instanceof LuaLocalDefinitionStatement) { LuaLocalDefinitionStatement stat = (LuaLocalDefinitionStatement) resolved.getContext().getContext(); LuaDeclarationExpression[] decls = stat.getDeclarations(); LuaExpression[] exprs = stat.getExprs(); if (exprs != null && exprs.length > 0) { LuaExpression aliasedExpression = null; for (int i = 0; i < decls.length; i++) { if (decls[i] == resolved && exprs.length > i) aliasedExpression = exprs[i]; } if (aliasedExpression instanceof LuaReferenceElement) { return (LuaReferenceElement) aliasedExpression; } } } return null; } }