diff --git a/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java b/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java index cc283d0bb2b7..bef3d0350563 100644 --- a/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java +++ b/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java @@ -86,7 +86,7 @@ public interface PsiSearchHelper { @NotNull GlobalSearchScope searchScope); /** - * Passes all occurrences of the specified full-qualified class name in plain text context in the + * Passes all occurrences of the specified fully qualified class name in plain text context in the * use scope of the specified element to the specified processor. * * @param originalElement the element whose use scope is used to restrict the search scope, @@ -126,7 +126,7 @@ public interface PsiSearchHelper { final boolean caseSensitively); /** - * Passes all files containing the specified word in {@link UsageSearchContext#IN_PLAIN_TEXT code} + * Passes all files containing the specified word in {@link UsageSearchContext#IN_PLAIN_TEXT plain text} * context to the specified processor. * * @param word the word to search. @@ -189,7 +189,7 @@ public interface PsiSearchHelper { @NotNull SearchCostResult isCheapEnoughToSearch(@NotNull String name, @NotNull GlobalSearchScope scope, - @Nullable PsiFile fileToIgnoreOccurencesIn, + @Nullable PsiFile fileToIgnoreOccurrencesIn, @Nullable ProgressIndicator progress); enum SearchCostResult { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java index 6dba855121cb..4cbd3cb01c19 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java @@ -10,10 +10,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiErrorElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiRecursiveElementWalkingVisitor; +import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.tree.LeafElement; import com.intellij.psi.search.GlobalSearchScope; @@ -26,6 +23,7 @@ import com.intellij.structuralsearch.impl.matcher.MatcherImplUtil; import com.intellij.structuralsearch.impl.matcher.PatternTreeContext; import com.intellij.structuralsearch.impl.matcher.filters.LexicalNodesFilter; import com.intellij.structuralsearch.impl.matcher.handlers.MatchPredicate; +import com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler; import com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler; import com.intellij.structuralsearch.impl.matcher.predicates.*; import com.intellij.structuralsearch.plugin.ui.Configuration; @@ -73,7 +71,9 @@ public class PatternCompiler { List elements = compileByAllPrefixes(project, options, result, context, prefixes); - context.getPattern().setNodes(elements); + final CompiledPattern pattern = context.getPattern(); + checkForUnknownVariables(pattern, elements); + pattern.setNodes(elements); if (context.getSearchHelper().doOptimizing() && context.getSearchHelper().isScannedSomething()) { final Set set = context.getSearchHelper().getFilesSetToScan(); @@ -105,6 +105,28 @@ public class PatternCompiler { return result; } + private static void checkForUnknownVariables(final CompiledPattern pattern, List elements) { + for (PsiElement element : elements) { + element.accept(new PsiRecursiveElementWalkingVisitor() { + @Override + public void visitElement(PsiElement element) { + if (element instanceof PsiComment) { + return; + } + super.visitElement(element); + + if (!(element instanceof LeafElement) || !pattern.isTypedVar(element)) { + return; + } + final MatchingHandler handler = pattern.getHandler(pattern.getTypedVarString(element)); + if (handler == null) { + throw new MalformedPatternException(); + } + } + }); + } + } + public static String getLastFindPlan() { return ((TestModeOptimizingSearchHelper)lastTestingContext.getSearchHelper()).getSearchPlan(); } @@ -462,10 +484,9 @@ public class PatternCompiler { PsiElement[] matchStatements; try { - final String pattern = buf.toString(); - matchStatements = MatcherImplUtil.createTreeFromText(pattern, PatternTreeContext.Block, options.getFileType(), + matchStatements = MatcherImplUtil.createTreeFromText(buf.toString(), PatternTreeContext.Block, options.getFileType(), options.getDialect(), options.getPatternContext(), project, false); - if (matchStatements.length==0) throw new MalformedPatternException(pattern); + if (matchStatements.length==0) throw new MalformedPatternException(); } catch (IncorrectOperationException e) { throw new MalformedPatternException(e.getMessage()); } @@ -487,12 +508,11 @@ public class PatternCompiler { } private static void addScriptConstraint(String name, MatchVariableConstraint constraint, SubstitutionHandler handler) { - MatchPredicate predicate; if (constraint.getScriptCodeConstraint()!= null && constraint.getScriptCodeConstraint().length() > 2) { final String script = StringUtil.stripQuotesAroundValue(constraint.getScriptCodeConstraint()); final String s = ScriptSupport.checkValidScript(script); if (s != null) throw new MalformedPatternException("Script constraint for " + constraint.getName() + " has problem "+s); - predicate = new ScriptPredicate(name, script); + MatchPredicate predicate = new ScriptPredicate(name, script); addPredicate(handler,predicate); } } diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index f6f3d58ba384..2a5473a7cfb3 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -2948,8 +2948,20 @@ public class StructuralSearchTest extends StructuralSearchTestCase { String source = "{}"; String pattern1 = "/*$A$a*/"; + MalformedPatternException ex = null; try { findMatchesCount(source, pattern1); - } catch (MalformedPatternException ignore) {} + } catch (MalformedPatternException e) { + ex = e; + } + assertNotNull(ex); + + String pattern2 = "class $A$Visitor {}"; + try { + findMatchesCount(source, pattern2); + } catch (MalformedPatternException e) { + ex = e; + } + assertNotNull(ex); } }