use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.
the class PatternCompiler method doCompile.
private static List<PsiElement> doCompile(Project project, MatchOptions options, CompiledPattern result, PrefixProvider prefixProvider, CompileContext context) {
result.clearHandlers();
context.init(result, options, project, options.getScope() instanceof GlobalSearchScope);
final StringBuilder buf = new StringBuilder();
Template template = TemplateManager.getInstance(project).createTemplate("", "", options.getSearchPattern());
int segmentsCount = template.getSegmentsCount();
String text = template.getTemplateText();
buf.setLength(0);
int prevOffset = 0;
for (int i = 0; i < segmentsCount; ++i) {
final int offset = template.getSegmentOffset(i);
final String name = template.getSegmentName(i);
final String prefix = prefixProvider.getPrefix(i);
if (prefix == null) {
throw new MalformedPatternException();
}
buf.append(text.substring(prevOffset, offset));
buf.append(prefix);
buf.append(name);
MatchVariableConstraint constraint = options.getVariableConstraint(name);
if (constraint == null) {
// we do not edited the constraints
constraint = new MatchVariableConstraint();
constraint.setName(name);
options.addVariableConstraint(constraint);
}
SubstitutionHandler handler = result.createSubstitutionHandler(name, prefix + name, constraint.isPartOfSearchResults(), constraint.getMinCount(), constraint.getMaxCount(), constraint.isGreedy());
if (constraint.isWithinHierarchy()) {
handler.setSubtype(true);
}
if (constraint.isStrictlyWithinHierarchy()) {
handler.setStrictSubtype(true);
}
MatchPredicate predicate;
if (!StringUtil.isEmptyOrSpaces(constraint.getRegExp())) {
predicate = new RegExpPredicate(constraint.getRegExp(), options.isCaseSensitiveMatch(), name, constraint.isWholeWordsOnly(), constraint.isPartOfSearchResults());
if (constraint.isInvertRegExp()) {
predicate = new NotPredicate(predicate);
}
addPredicate(handler, predicate);
}
if (constraint.isReference()) {
predicate = new ReferencePredicate(constraint.getNameOfReferenceVar());
if (constraint.isInvertReference()) {
predicate = new NotPredicate(predicate);
}
addPredicate(handler, predicate);
}
addExtensionPredicates(options, constraint, handler);
addScriptConstraint(project, name, constraint, handler);
if (!StringUtil.isEmptyOrSpaces(constraint.getContainsConstraint())) {
predicate = new ContainsPredicate(name, constraint.getContainsConstraint());
if (constraint.isInvertContainsConstraint()) {
predicate = new NotPredicate(predicate);
}
addPredicate(handler, predicate);
}
if (!StringUtil.isEmptyOrSpaces(constraint.getWithinConstraint())) {
assert false;
}
prevOffset = offset;
}
MatchVariableConstraint constraint = options.getVariableConstraint(Configuration.CONTEXT_VAR_NAME);
if (constraint != null) {
SubstitutionHandler handler = result.createSubstitutionHandler(Configuration.CONTEXT_VAR_NAME, Configuration.CONTEXT_VAR_NAME, constraint.isPartOfSearchResults(), constraint.getMinCount(), constraint.getMaxCount(), constraint.isGreedy());
if (!StringUtil.isEmptyOrSpaces(constraint.getWithinConstraint())) {
MatchPredicate predicate = new WithinPredicate(Configuration.CONTEXT_VAR_NAME, constraint.getWithinConstraint(), options.getFileType(), project);
if (constraint.isInvertWithinConstraint()) {
predicate = new NotPredicate(predicate);
}
addPredicate(handler, predicate);
}
addExtensionPredicates(options, constraint, handler);
addScriptConstraint(project, Configuration.CONTEXT_VAR_NAME, constraint, handler);
}
buf.append(text.substring(prevOffset, text.length()));
PsiElement[] matchStatements;
try {
matchStatements = MatcherImplUtil.createTreeFromText(buf.toString(), PatternTreeContext.Block, options.getFileType(), options.getDialect(), options.getPatternContext(), project, false);
if (matchStatements.length == 0)
throw new MalformedPatternException();
} catch (IncorrectOperationException e) {
throw new MalformedPatternException(e.getMessage());
}
NodeFilter filter = LexicalNodesFilter.getInstance();
GlobalCompilingVisitor compilingVisitor = new GlobalCompilingVisitor();
compilingVisitor.compile(matchStatements, context);
ArrayList<PsiElement> elements = new ArrayList<>();
for (PsiElement matchStatement : matchStatements) {
if (!filter.accepts(matchStatement)) {
elements.add(matchStatement);
}
}
new DeleteNodesAction(compilingVisitor.getLexicalNodes()).run();
return elements;
}
use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.
the class JavaMatchingVisitor method matchType.
private boolean matchType(final PsiElement patternType, final PsiElement matchedType) {
PsiElement patternElement = getInnermostComponent(patternType);
PsiElement matchedElement = getInnermostComponent(matchedType);
PsiElement[] typeParameters = null;
if (matchedElement instanceof PsiJavaCodeReferenceElement) {
final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) matchedElement;
typeParameters = getTypeParameters(referenceElement, !hasDiamondTypeParameter(patternElement));
} else if (matchedElement instanceof PsiTypeParameter) {
matchedElement = ((PsiTypeParameter) matchedElement).getNameIdentifier();
} else if (matchedElement instanceof PsiClass && ((PsiClass) matchedElement).hasTypeParameters()) {
typeParameters = ((PsiClass) matchedElement).getTypeParameters();
matchedElement = ((PsiClass) matchedElement).getNameIdentifier();
} else if (matchedElement instanceof PsiMethod && ((PsiMethod) matchedElement).hasTypeParameters()) {
typeParameters = ((PsiMethod) matchedType).getTypeParameters();
matchedElement = ((PsiMethod) matchedType).getNameIdentifier();
}
if (patternElement instanceof PsiJavaCodeReferenceElement) {
final PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) patternElement;
final PsiReferenceParameterList list = referenceElement.getParameterList();
if (list != null) {
final PsiTypeElement[] elements = list.getTypeParameterElements();
if (elements.length > 0 && (typeParameters == null || !myMatchingVisitor.matchSequentially(elements, typeParameters))) {
return false;
}
}
patternElement = referenceElement.getReferenceNameElement();
}
final int matchedArrayDimensions = getArrayDimensions(matchedType);
final int patternArrayDimensions = getArrayDimensions(patternType);
if (myMatchingVisitor.getMatchContext().getPattern().isTypedVar(patternElement)) {
final SubstitutionHandler handler = (SubstitutionHandler) myMatchingVisitor.getMatchContext().getPattern().getHandler(patternElement);
RegExpPredicate regExpPredicate = null;
if (patternArrayDimensions != 0) {
if (patternArrayDimensions != matchedArrayDimensions) {
return false;
}
} else if (matchedArrayDimensions != 0) {
regExpPredicate = MatchingHandler.getSimpleRegExpPredicate(handler);
if (regExpPredicate != null) {
regExpPredicate.setNodeTextGenerator(new RegExpPredicate.NodeTextGenerator() {
public String getText(PsiElement element) {
StringBuilder builder = new StringBuilder(RegExpPredicate.getMeaningfulText(element));
for (int i = 0; i < matchedArrayDimensions; ++i) builder.append("[]");
return builder.toString();
}
});
}
}
try {
if (handler.isSubtype() || handler.isStrictSubtype()) {
return checkMatchWithinHierarchy(matchedElement, handler, patternElement);
} else {
return handler.handle(matchedElement, myMatchingVisitor.getMatchContext());
}
} finally {
if (regExpPredicate != null)
regExpPredicate.setNodeTextGenerator(null);
}
}
if (matchedArrayDimensions != patternArrayDimensions) {
return false;
}
if (patternElement instanceof PsiIdentifier) {
final PsiElement parent = patternElement.getParent();
if (parent instanceof PsiJavaCodeReferenceElement) {
patternElement = parent;
}
}
if (matchedElement instanceof PsiIdentifier) {
final PsiElement parent = matchedElement.getParent();
if (parent instanceof PsiJavaCodeReferenceElement) {
matchedElement = parent;
}
}
final String text = getText(patternElement);
final String text2 = getText(matchedElement);
final boolean caseSensitive = myMatchingVisitor.getMatchContext().getOptions().isCaseSensitiveMatch();
final boolean equalsIgnorePackage = MatchUtils.compareWithNoDifferenceToPackage(text, text2, !caseSensitive);
if (equalsIgnorePackage || !(matchedElement instanceof PsiJavaReference)) {
return equalsIgnorePackage;
} else {
final PsiElement element2 = ((PsiJavaReference) matchedElement).resolve();
if (!(element2 instanceof PsiClass)) {
return false;
}
final String name = ((PsiClass) element2).getQualifiedName();
return caseSensitive ? text.equals(name) : text.equalsIgnoreCase(name);
}
}
use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.
the class JavaMatchingVisitor method visitTypeParameter.
@Override
public void visitTypeParameter(PsiTypeParameter psiTypeParameter) {
final PsiTypeParameter parameter = (PsiTypeParameter) myMatchingVisitor.getElement();
final PsiIdentifier identifier = psiTypeParameter.getNameIdentifier();
final PsiIdentifier identifier2 = parameter.getNameIdentifier();
final MatchingHandler handler = myMatchingVisitor.getMatchContext().getPattern().getHandler(identifier);
if (handler instanceof SubstitutionHandler) {
myMatchingVisitor.setResult(((SubstitutionHandler) handler).handle(identifier2, myMatchingVisitor.getMatchContext()));
} else {
myMatchingVisitor.setResult(myMatchingVisitor.matchText(identifier, identifier2));
}
if (myMatchingVisitor.getResult()) {
myMatchingVisitor.setResult(matchInAnyOrder(psiTypeParameter.getExtendsList(), parameter.getExtendsList()));
}
if (myMatchingVisitor.getResult()) {
myMatchingVisitor.setResult(myMatchingVisitor.matchInAnyOrder(psiTypeParameter.getAnnotations(), parameter.getAnnotations()));
}
}
use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.
the class JavaMatchingVisitor method compareClasses.
private boolean compareClasses(final PsiClass clazz, final PsiClass clazz2) {
final PsiClass saveClazz = this.myClazz;
final MatchContext.MatchedElementsListener oldListener = myMatchingVisitor.getMatchContext().getMatchedElementsListener();
this.myClazz = clazz2;
final CompiledPattern pattern = myMatchingVisitor.getMatchContext().getPattern();
assert pattern instanceof JavaCompiledPattern;
final JavaCompiledPattern javaPattern = (JavaCompiledPattern) pattern;
MatchContext.MatchedElementsListener listener = new MatchContext.MatchedElementsListener() {
private Set<PsiElement> myMatchedElements;
@Override
public void matchedElements(Collection<PsiElement> matchedElements) {
if (matchedElements == null)
return;
if (myMatchedElements == null) {
myMatchedElements = new HashSet<>(matchedElements);
} else {
myMatchedElements.addAll(matchedElements);
}
}
@Override
public void commitUnmatched() {
final List<PsiMember> members = PsiTreeUtil.getChildrenOfTypeAsList(clazz2, PsiMember.class);
final List<PsiMember> unmatchedElements = ContainerUtil.filter(members, a -> myMatchedElements == null || !myMatchedElements.contains(a));
MatchingHandler unmatchedSubstitutionHandler = null;
for (PsiElement element = clazz.getFirstChild(); element != null; element = element.getNextSibling()) {
if (element instanceof PsiTypeElement && element.getNextSibling() instanceof PsiErrorElement) {
unmatchedSubstitutionHandler = pattern.getHandler(element);
break;
}
}
if (unmatchedSubstitutionHandler instanceof SubstitutionHandler) {
final SubstitutionHandler handler = (SubstitutionHandler) unmatchedSubstitutionHandler;
for (PsiMember element : unmatchedElements) {
handler.handle(element, myMatchingVisitor.getMatchContext());
}
} else {
clazz2.putUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY, unmatchedElements);
}
}
};
myMatchingVisitor.getMatchContext().setMatchedElementsListener(listener);
boolean result = false;
try {
final boolean templateIsInterface = clazz.isInterface();
if (templateIsInterface != clazz2.isInterface())
return false;
if (templateIsInterface && clazz.isAnnotationType() && !clazz2.isAnnotationType())
return false;
if (clazz.isEnum() && !clazz2.isEnum())
return false;
if (!matchInAnyOrder(clazz.getExtendsList(), clazz2.getExtendsList())) {
return false;
}
// check if implements is in extended classes implements
final PsiReferenceList implementsList = clazz.getImplementsList();
if (implementsList != null) {
if (!matchInAnyOrder(implementsList, clazz2.getImplementsList())) {
final PsiReferenceList anotherExtendsList = clazz2.getExtendsList();
final PsiJavaCodeReferenceElement[] referenceElements = implementsList.getReferenceElements();
boolean accepted = false;
if (referenceElements.length > 0 && anotherExtendsList != null) {
final HierarchyNodeIterator iterator = new HierarchyNodeIterator(clazz2, true, true, false);
accepted = myMatchingVisitor.matchInAnyOrder(new ArrayBackedNodeIterator(referenceElements), iterator);
}
if (!accepted)
return false;
}
}
final PsiField[] fields = clazz.getFields();
if (fields.length > 0) {
final PsiField[] fields2 = javaPattern.isRequestsSuperFields() ? clazz2.getAllFields() : clazz2.getFields();
if (!myMatchingVisitor.matchInAnyOrder(fields, fields2)) {
return false;
}
}
final PsiMethod[] methods = clazz.getMethods();
if (methods.length > 0) {
final PsiMethod[] methods2 = javaPattern.isRequestsSuperMethods() ? clazz2.getAllMethods() : clazz2.getMethods();
if (!myMatchingVisitor.matchInAnyOrder(methods, methods2)) {
return false;
}
}
final PsiClass[] nestedClasses = clazz.getInnerClasses();
if (nestedClasses.length > 0) {
final PsiClass[] nestedClasses2 = javaPattern.isRequestsSuperInners() ? clazz2.getAllInnerClasses() : clazz2.getInnerClasses();
if (!myMatchingVisitor.matchInAnyOrder(nestedClasses, nestedClasses2)) {
return false;
}
}
final PsiClassInitializer[] initializers = clazz.getInitializers();
if (initializers.length > 0) {
final PsiClassInitializer[] initializers2 = clazz2.getInitializers();
if (!myMatchingVisitor.matchInAnyOrder(initializers, initializers2)) {
return false;
}
}
result = true;
return true;
} finally {
if (result)
listener.commitUnmatched();
this.myClazz = saveClazz;
myMatchingVisitor.getMatchContext().setMatchedElementsListener(oldListener);
}
}
use of com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler in project intellij-community by JetBrains.
the class JavaMatchingVisitor method matchImplicitQualifier.
private void matchImplicitQualifier(MatchingHandler matchingHandler, PsiElement target, MatchContext context) {
if (!(matchingHandler instanceof SubstitutionHandler)) {
myMatchingVisitor.setResult(false);
return;
}
final SubstitutionHandler substitutionHandler = (SubstitutionHandler) matchingHandler;
final MatchPredicate predicate = substitutionHandler.getPredicate();
if (substitutionHandler.getMinOccurs() != 0) {
myMatchingVisitor.setResult(false);
return;
}
if (predicate == null) {
myMatchingVisitor.setResult(true);
return;
}
if (target == null) {
myMatchingVisitor.setResult(false);
return;
}
if (target instanceof PsiModifierListOwner && ((PsiModifierListOwner) target).hasModifierProperty(PsiModifier.STATIC)) {
myMatchingVisitor.setResult(predicate.match(null, PsiTreeUtil.getParentOfType(target, PsiClass.class), context));
} else {
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(target.getProject());
final PsiExpression implicitReference = factory.createExpressionFromText("this", target);
myMatchingVisitor.setResult(predicate.match(null, implicitReference, context));
}
}
Aggregations