SSR: add javadoc

GitOrigin-RevId: 5431780a0728d4cb9724c2f09403a4f81dd2d24e
This commit is contained in:
Bas Leijdekkers
2020-04-20 08:03:39 +00:00
committed by intellij-monorepo-bot
parent 4656d2b4db
commit 12ff3a9f28
7 changed files with 97 additions and 33 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher.handlers;
import com.intellij.psi.PsiElement;
@@ -6,18 +6,16 @@ import com.intellij.psi.PsiExpressionStatement;
import com.intellij.structuralsearch.impl.matcher.MatchContext;
/**
* Handler for substitution expression search
* Handler for expression search. The pattern for an expression includes an unnecessary {@code PsiExpressionStatement},
* this is skipped by this {@code MatchingHandler}
*/
public class ExpressionHandler extends MatchingHandler {
@Override
public boolean match(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
if (!super.match(patternNode,matchedNode,context)) {
if (!super.match(patternNode,matchedNode, context)) {
return false;
}
return context.getMatcher().match(
((PsiExpressionStatement)patternNode).getExpression(),
matchedNode
);
return context.getMatcher().match(((PsiExpressionStatement)patternNode).getExpression(), matchedNode);
}
}
@@ -33,6 +33,8 @@ import java.util.Collections;
import java.util.List;
/**
* Entry point for supporting a specific language in Structural Search.
*
* @author Eugene.Kudelevsky
*/
public abstract class StructuralSearchProfile {
@@ -40,14 +42,43 @@ public abstract class StructuralSearchProfile {
ExtensionPointName.create("com.intellij.structuralsearch.profile");
@NonNls protected static final String PATTERN_PLACEHOLDER = "$$PATTERN_PLACEHOLDER$$";
/**
* Creates the pattern PSI tree which is stored inside CompiledPattern.
* Uses compiling visitor to visit the query PsiElements, sets the correct Filters and Handlers.
* @see #createCompiledPattern()
* @param elements
* @param globalVisitor
*/
public abstract void compile(PsiElement[] elements, @NotNull GlobalCompilingVisitor globalVisitor);
/**
* The MatchingVisitor knows how to match language specific constructs, when those constructs have already been found.
*
* <p>For example {@code if} statements in Java: first the condition of the pattern is compared to the condition of the found
* {@code if} statement. If it matches, compare the then part of the {@code if} statement. And if the pattern has an
* {@code else} part, try to match that as well. If no {@code else} is present in the pattern, just ignore any {@code else} in the code.
*
* <p>In some cases MatchingVisitor also knows how to match two not quite similar things as well,
* like {@code String s = "";} and {@code var s = "";} in Java, if {@code s} has the same inferred type as the explicit type in
* the pattern.
*
* @param globalVisitor the global matching visitor which the created matching visitor can use to e.g. retrieve the current element to match.
* @return a language specific matching visitor
*/
@NotNull
public abstract PsiElementVisitor createMatchingVisitor(@NotNull GlobalMatchingVisitor globalVisitor);
/**
* Filter to filter out uninteresting elements that should not be matched. Usually white space and error elements.
* @return
*/
@NotNull
public abstract NodeFilter getLexicalNodesFilter();
/**
* Creates language specific compiled pattern.
* @return
*/
@NotNull
public abstract CompiledPattern createCompiledPattern();
@@ -56,8 +87,23 @@ public abstract class StructuralSearchProfile {
return Collections.emptyList();
}
/**
* @param language
* @return true, if this structural search profile can match code of the specified language. False otherwise.
*/
public abstract boolean isMyLanguage(@NotNull Language language);
/**
* Converts query text into PSI tree.
* @param text the text of the search query.
* @param context
* @param fileType
* @param language
* @param contextId
* @param project
* @param physical
* @return
*/
@NotNull
public PsiElement[] createPatternTree(@NotNull String text,
@NotNull PatternTreeContext context,
@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher;
import com.intellij.dupLocator.iterators.ArrayBackedNodeIterator;
@@ -24,7 +24,8 @@ import java.util.List;
import java.util.Map;
/**
* Class to hold compiled pattern information
* Class to hold compiled pattern information. Contains the PSI pattern tree, and maps PsiElements to matching handlers.
* @see MatchingHandler
*/
public abstract class CompiledPattern {
public static final Key<Object> HANDLER_KEY = Key.create("ss.handler");
@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher;
import com.intellij.dupLocator.AbstractMatchingVisitor;
@@ -30,23 +30,32 @@ import java.util.Map;
import static com.intellij.structuralsearch.impl.matcher.iterators.SingleNodeIterator.newSingleNodeIterator;
/**
* Visitor class to manage pattern matching
* GlobalMatchingVisitor does the walking of the pattern tree, and invokes the language specific MatchingVisitor on elements.
* It also stores the current code element to match. MatchingVisitor visits pattern elements, not code elements.
* A language specific matching visitor can retrieve the current code element from the GlobalMatchingVisitor by calling
* {@link #getElement()} from inside the visit methods.
*/
public class GlobalMatchingVisitor extends AbstractMatchingVisitor {
private static final Logger LOG = Logger.getInstance(GlobalMatchingVisitor.class);
public static final Key<List<? extends PsiElement>> UNMATCHED_ELEMENTS_KEY = Key.create("UnmatchedElements");
// the pattern element for visitor check
/**
* The current element to match.
*/
private PsiElement myElement;
// the result of matching in visitor
/**
* The result of matching in visitor
*/
private boolean myResult;
// context of matching
private MatchContext matchContext;
private final Map<Language, PsiElementVisitor> myLanguage2MatchingVisitor = new HashMap<>(1);
/**
* @return the current code element to match.
*/
public PsiElement getElement() {
return myElement;
}
@@ -105,31 +114,31 @@ public class GlobalMatchingVisitor extends AbstractMatchingVisitor {
/**
* Identifies the match between given element of program tree and pattern element
*
* @param el1 the pattern for matching
* @param el2 the tree element for matching
* @param patternElement the pattern element
* @param matchElement the match element from the code.
* @return true if equal and false otherwise
*/
@Override
public boolean match(PsiElement el1, PsiElement el2) {
public boolean match(PsiElement patternElement, PsiElement matchElement) {
ProgressManager.checkCanceled();
if (el1 == el2) return true;
if (el1 == null) {
if (patternElement == matchElement) return true;
if (patternElement == null) {
// absence of pattern element is match
return true;
}
if (el2 == null) {
if (matchElement == null) {
// absence of match element needs check if allowed.
return allowsAbsenceOfMatch(el1);
return allowsAbsenceOfMatch(patternElement);
}
// copy changed data to local stack
PsiElement prevElement = myElement;
myElement = el2;
myElement = matchElement;
try {
PsiElementVisitor visitor = getVisitorForElement(el1);
PsiElementVisitor visitor = getVisitorForElement(patternElement);
if (visitor != null) {
el1.accept(visitor);
patternElement.accept(visitor);
}
}
catch (ClassCastException ex) {
@@ -183,9 +192,9 @@ public class GlobalMatchingVisitor extends AbstractMatchingVisitor {
}
/**
* Descents the tree in depth finding matches
* Descends the tree in depth finding matches
*
* @param elements the element for which the sons are looked for match
* @param elements the element of which the children are checked for a match
*/
public void matchContext(@NotNull NodeIterator elements) {
final CompiledPattern pattern = matchContext.getPattern();
@@ -1,4 +1,4 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher.compiler;
import com.intellij.openapi.project.Project;
@@ -12,6 +12,10 @@ import java.util.Collections;
import java.util.List;
/**
* The WordOptimizer is used for extracting words to check in the index. Basically it is just an optimization for faster search,
* because files without the extracted words don’t need to be scanned. That means you can create Structural Search for a language
* without a WordOptimizer and it will still be correct, just slower.
*
* @author Bas Leijdekkers
*/
public interface WordOptimizer {
@@ -1,4 +1,4 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher.handlers;
import com.intellij.dupLocator.iterators.NodeIterator;
@@ -18,12 +18,18 @@ import java.util.HashSet;
import java.util.Set;
/**
* Root of handlers for pattern node matching. Handles simplest type of the match.
* Root of handlers for pattern node matching. Matching handlers know how to match a specific pattern node
* to a node in the source code.
*/
public abstract class MatchingHandler {
protected NodeFilter filter;
private PsiElement pinnedElement;
/**
* Node filters determine which kind of PsiElements can match the pattern element.
* Filters are applied to MatchingHandlers in the CompilingVisitor.
* @param filter
*/
public void setFilter(NodeFilter filter) {
this.filter = filter;
}
@@ -1,11 +1,11 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.structuralsearch.impl.matcher.handlers;
import com.intellij.psi.PsiElement;
import com.intellij.structuralsearch.impl.matcher.MatchContext;
/**
* Root of handlers for pattern node matching. Handles simplest type of the match.
* Handles simplest type of the match: one node from the pattern to one node of the code.
*/
public final class SimpleHandler extends MatchingHandler {
/**
@@ -16,7 +16,7 @@ public final class SimpleHandler extends MatchingHandler {
*/
@Override
public boolean match(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
if (!super.match(patternNode,matchedNode,context)) return false;
return context.getMatcher().match(patternNode,matchedNode);
if (!super.match(patternNode, matchedNode, context)) return false;
return context.getMatcher().match(patternNode, matchedNode);
}
}