| package com.intellij.structuralsearch.impl.matcher.compiler; |
| |
| import com.intellij.dupLocator.iterators.NodeIterator; |
| import com.intellij.psi.*; |
| import com.intellij.psi.javadoc.PsiDocComment; |
| import com.intellij.psi.javadoc.PsiDocTag; |
| import com.intellij.psi.search.*; |
| import com.intellij.psi.search.searches.ClassInheritorsSearch; |
| import com.intellij.structuralsearch.*; |
| import com.intellij.structuralsearch.impl.matcher.CompiledPattern; |
| import com.intellij.structuralsearch.impl.matcher.JavaCompiledPattern; |
| import com.intellij.structuralsearch.impl.matcher.filters.*; |
| import com.intellij.structuralsearch.impl.matcher.handlers.*; |
| import com.intellij.structuralsearch.impl.matcher.iterators.DocValuesIterator; |
| import com.intellij.structuralsearch.impl.matcher.predicates.RegExpPredicate; |
| import com.intellij.structuralsearch.impl.matcher.strategies.*; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { |
| private final GlobalCompilingVisitor myCompilingVisitor; |
| |
| @NonNls private static final String COMMENT = "\\s*(__\\$_\\w+)\\s*"; |
| private static final Pattern ourPattern = Pattern.compile("//" + COMMENT, Pattern.DOTALL); |
| private static final Pattern ourPattern2 = Pattern.compile("/\\*" + COMMENT + "\\*/", Pattern.DOTALL); |
| private static final Pattern ourPattern3 = Pattern.compile("/\\*\\*" + COMMENT + "\\*/", Pattern.DOTALL); |
| |
| public JavaCompilingVisitor(GlobalCompilingVisitor compilingVisitor) { |
| this.myCompilingVisitor = compilingVisitor; |
| } |
| |
| @Override |
| public void visitDocTag(PsiDocTag psiDocTag) { |
| super.visitDocTag(psiDocTag); |
| |
| NodeIterator sons = new DocValuesIterator(psiDocTag.getFirstChild()); |
| while (sons.hasNext()) { |
| myCompilingVisitor.setHandler(sons.current(), new DocDataHandler()); |
| sons.advance(); |
| } |
| } |
| |
| @Override |
| public void visitComment(PsiComment comment) { |
| super.visitComment(comment); |
| |
| final String text = comment.getText(); |
| Matcher matcher = ourPattern.matcher(text); |
| boolean matches = false; |
| if (!matcher.matches()) { |
| matcher = ourPattern2.matcher(text); |
| |
| if (!matcher.matches()) { |
| matcher = ourPattern3.matcher(text); |
| } |
| else { |
| matches = true; |
| } |
| } |
| else { |
| matches = true; |
| } |
| |
| if (matches || matcher.matches()) { |
| String str = matcher.group(1); |
| comment.putUserData(CompiledPattern.HANDLER_KEY, str); |
| |
| GlobalCompilingVisitor.setFilter( |
| myCompilingVisitor.getContext().getPattern().getHandler(comment), |
| CommentFilter.getInstance() |
| ); |
| |
| SubstitutionHandler handler = (SubstitutionHandler)myCompilingVisitor.getContext().getPattern().getHandler(str); |
| if (handler == null) { |
| throw new MalformedPatternException(); |
| } |
| |
| if (handler.getPredicate() != null) { |
| ((RegExpPredicate)handler.getPredicate()).setMultiline(true); |
| } |
| |
| RegExpPredicate predicate = MatchingHandler.getSimpleRegExpPredicate(handler); |
| if (GlobalCompilingVisitor.isSuitablePredicate(predicate, handler)) { |
| myCompilingVisitor.processTokenizedName(predicate.getRegExp(), true, GlobalCompilingVisitor.OccurenceKind.COMMENT); |
| } |
| |
| matches = true; |
| } |
| |
| if (!matches) { |
| MatchingHandler handler = myCompilingVisitor.processPatternStringWithFragments(text, GlobalCompilingVisitor.OccurenceKind.COMMENT); |
| if (handler != null) comment.putUserData(CompiledPattern.HANDLER_KEY, handler); |
| } |
| } |
| |
| @Override |
| public void visitLiteralExpression(PsiLiteralExpression expression) { |
| String value = expression.getText(); |
| |
| if (value.length() > 2 && value.charAt(0) == '"' && value.charAt(value.length() - 1) == '"') { |
| @Nullable MatchingHandler handler = |
| myCompilingVisitor.processPatternStringWithFragments(value, GlobalCompilingVisitor.OccurenceKind.LITERAL); |
| |
| if (handler != null) { |
| expression.putUserData(CompiledPattern.HANDLER_KEY, handler); |
| } |
| } |
| super.visitLiteralExpression(expression); |
| } |
| |
| @Override |
| public void visitClassInitializer(final PsiClassInitializer initializer) { |
| super.visitClassInitializer(initializer); |
| PsiStatement[] psiStatements = initializer.getBody().getStatements(); |
| if (psiStatements.length == 1 && psiStatements[0] instanceof PsiExpressionStatement) { |
| MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(psiStatements[0]); |
| |
| if (handler instanceof SubstitutionHandler) { |
| myCompilingVisitor.getContext().getPattern().setHandler(initializer, new SubstitutionHandler((SubstitutionHandler)handler)); |
| } |
| } |
| } |
| |
| @Override |
| public void visitField(PsiField psiField) { |
| super.visitField(psiField); |
| CompiledPattern pattern = myCompilingVisitor.getContext().getPattern(); |
| final MatchingHandler handler = pattern.getHandler(psiField); |
| |
| if (needsSupers(psiField, handler)) { |
| assert pattern instanceof JavaCompiledPattern; |
| ((JavaCompiledPattern)pattern).setRequestsSuperFields(true); |
| } |
| } |
| |
| @Override |
| public void visitMethod(PsiMethod psiMethod) { |
| super.visitMethod(psiMethod); |
| CompiledPattern pattern = myCompilingVisitor.getContext().getPattern(); |
| final MatchingHandler handler = pattern.getHandler(psiMethod); |
| |
| if (needsSupers(psiMethod, handler)) { |
| assert pattern instanceof JavaCompiledPattern; |
| ((JavaCompiledPattern)pattern).setRequestsSuperMethods(true); |
| } |
| |
| GlobalCompilingVisitor.setFilter(handler, MethodFilter.getInstance()); |
| handleReferenceText(psiMethod.getName(), myCompilingVisitor.getContext()); |
| } |
| |
| @Override |
| public void visitReferenceExpression(PsiReferenceExpression reference) { |
| visitElement(reference); |
| |
| boolean typedVarProcessed = false; |
| final PsiElement referenceParent = reference.getParent(); |
| |
| if ((myCompilingVisitor.getContext().getPattern().isRealTypedVar(reference)) && |
| reference.getQualifierExpression() == null && |
| !(referenceParent instanceof PsiExpressionStatement) |
| ) { |
| // typed var for expression (but not top level) |
| MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(reference); |
| GlobalCompilingVisitor.setFilter(handler, ExpressionFilter.getInstance()); |
| typedVarProcessed = true; |
| } |
| |
| if (!(referenceParent instanceof PsiMethodCallExpression)) { |
| handleReference(reference); |
| } |
| |
| MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(reference); |
| |
| // We want to merge qname related to class to find it in any form |
| final String referencedName = reference.getReferenceName(); |
| |
| if (!typedVarProcessed && |
| !(handler instanceof SubstitutionHandler)) { |
| final PsiElement resolve = reference.resolve(); |
| |
| PsiElement referenceQualifier = reference.getQualifier(); |
| if (resolve instanceof PsiClass || |
| (resolve == null && |
| ((referencedName != null && Character.isUpperCase(referencedName.charAt(0))) || |
| referenceQualifier == null |
| ) |
| ) |
| ) { |
| boolean hasNoNestedSubstitutionHandlers = false; |
| PsiExpression qualifier; |
| PsiReferenceExpression currentReference = reference; |
| |
| while ((qualifier = currentReference.getQualifierExpression()) != null) { |
| if (!(qualifier instanceof PsiReferenceExpression) || |
| myCompilingVisitor.getContext().getPattern().getHandler(qualifier) instanceof SubstitutionHandler |
| ) { |
| hasNoNestedSubstitutionHandlers = true; |
| break; |
| } |
| currentReference = (PsiReferenceExpression)qualifier; |
| } |
| if (!hasNoNestedSubstitutionHandlers) { |
| createAndSetSubstitutionHandlerFromReference( |
| reference, |
| resolve != null ? ((PsiClass)resolve).getQualifiedName() : reference.getText(), |
| referenceParent instanceof PsiExpression |
| ); |
| } |
| } |
| else if (referenceQualifier != null && reference.getParent() instanceof PsiExpressionStatement) { |
| //Handler qualifierHandler = context.pattern.getHandler(referenceQualifier); |
| //if (qualifierHandler instanceof SubstitutionHandler && |
| // !context.pattern.isRealTypedVar(reference) |
| // ) { |
| // createAndSetSubstitutionHandlerFromReference(reference, referencedName); |
| // |
| // SubstitutionHandler substitutionHandler = (SubstitutionHandler)qualifierHandler; |
| // RegExpPredicate expPredicate = Handler.getSimpleRegExpPredicate(substitutionHandler); |
| // //if (expPredicate != null) |
| // // substitutionHandler.setPredicate(new ExprTypePredicate(expPredicate.getRegExp(), null, true, true, false)); |
| //} |
| } |
| } |
| } |
| |
| @Override |
| public void visitMethodCallExpression(PsiMethodCallExpression expression) { |
| handleReference(expression.getMethodExpression()); |
| super.visitMethodCallExpression(expression); |
| } |
| |
| @Override |
| public void visitBlockStatement(PsiBlockStatement psiBlockStatement) { |
| super.visitBlockStatement(psiBlockStatement); |
| myCompilingVisitor.getContext().getPattern().getHandler(psiBlockStatement).setFilter(BlockFilter.getInstance()); |
| } |
| |
| @Override |
| public void visitVariable(PsiVariable psiVariable) { |
| super.visitVariable(psiVariable); |
| myCompilingVisitor.getContext().getPattern().getHandler(psiVariable).setFilter(VariableFilter.getInstance()); |
| handleReferenceText(psiVariable.getName(), myCompilingVisitor.getContext()); |
| } |
| |
| @Override |
| public void visitDeclarationStatement(PsiDeclarationStatement psiDeclarationStatement) { |
| super.visitDeclarationStatement(psiDeclarationStatement); |
| |
| if (psiDeclarationStatement.getFirstChild() instanceof PsiTypeElement) { |
| // search for expression or symbol |
| final PsiJavaCodeReferenceElement reference = |
| ((PsiTypeElement)psiDeclarationStatement.getFirstChild()).getInnermostComponentReferenceElement(); |
| |
| if (reference != null && |
| (myCompilingVisitor.getContext().getPattern().isRealTypedVar(reference.getReferenceNameElement())) && |
| reference.getParameterList().getTypeParameterElements().length > 0 |
| ) { |
| myCompilingVisitor.setHandler(psiDeclarationStatement, new TypedSymbolHandler()); |
| final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(psiDeclarationStatement); |
| // typed symbol |
| handler.setFilter( |
| TypedSymbolNodeFilter.getInstance() |
| ); |
| |
| final PsiTypeElement[] params = reference.getParameterList().getTypeParameterElements(); |
| for (PsiTypeElement param : params) { |
| if (param.getInnermostComponentReferenceElement() != null && |
| (myCompilingVisitor.getContext().getPattern().isRealTypedVar( |
| param.getInnermostComponentReferenceElement().getReferenceNameElement())) |
| ) { |
| myCompilingVisitor.getContext().getPattern().getHandler(param).setFilter( |
| TypeParameterFilter.getInstance() |
| ); |
| } |
| } |
| |
| return; |
| } |
| } |
| |
| final MatchingHandler handler = new DeclarationStatementHandler(); |
| myCompilingVisitor.getContext().getPattern().setHandler(psiDeclarationStatement, handler); |
| PsiElement previousNonWhiteSpace = psiDeclarationStatement.getPrevSibling(); |
| |
| while (previousNonWhiteSpace instanceof PsiWhiteSpace) { |
| previousNonWhiteSpace = previousNonWhiteSpace.getPrevSibling(); |
| } |
| |
| if (previousNonWhiteSpace instanceof PsiComment) { |
| ((DeclarationStatementHandler)handler) |
| .setCommentHandler(myCompilingVisitor.getContext().getPattern().getHandler(previousNonWhiteSpace)); |
| |
| myCompilingVisitor.getContext().getPattern().setHandler( |
| previousNonWhiteSpace, |
| handler |
| ); |
| } |
| |
| // detect typed symbol, it will have no variable |
| handler.setFilter(DeclarationFilter.getInstance()); |
| } |
| |
| @Override |
| public void visitDocComment(PsiDocComment psiDocComment) { |
| super.visitDocComment(psiDocComment); |
| myCompilingVisitor.getContext().getPattern().getHandler(psiDocComment).setFilter(JavaDocFilter.getInstance()); |
| } |
| |
| @Override |
| public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { |
| super.visitReferenceElement(reference); |
| |
| if (reference.getParent() != null && |
| reference.getParent().getParent() instanceof PsiClass) { |
| GlobalCompilingVisitor.setFilter(myCompilingVisitor.getContext().getPattern().getHandler(reference), TypeFilter.getInstance()); |
| } |
| |
| handleReference(reference); |
| } |
| |
| @Override |
| public void visitClass(PsiClass psiClass) { |
| super.visitClass(psiClass); |
| |
| CompiledPattern pattern = myCompilingVisitor.getContext().getPattern(); |
| final MatchingHandler handler = pattern.getHandler(psiClass); |
| |
| if (needsSupers(psiClass, handler)) { |
| ((JavaCompiledPattern)pattern).setRequestsSuperInners(true); |
| } |
| handleReferenceText(psiClass.getName(), myCompilingVisitor.getContext()); |
| |
| GlobalCompilingVisitor.setFilter(handler, ClassFilter.getInstance()); |
| |
| boolean hasSubstitutionHandler = false; |
| for (PsiElement element = psiClass.getFirstChild(); element != null; element = element.getNextSibling()) { |
| if (element instanceof PsiTypeElement && element.getNextSibling() instanceof PsiErrorElement) { |
| // found match that |
| MatchingHandler unmatchedSubstitutionHandler = pattern.getHandler(element); |
| if (unmatchedSubstitutionHandler != null) { |
| psiClass.putUserData(JavaCompiledPattern.ALL_CLASS_CONTENT_VAR_NAME_KEY, pattern.getTypedVarString(element)); |
| hasSubstitutionHandler = true; |
| } |
| } |
| } |
| |
| if (!hasSubstitutionHandler) { |
| String name = CompiledPattern.ALL_CLASS_UNMATCHED_CONTENT_VAR_ARTIFICIAL_NAME; |
| psiClass.putUserData(JavaCompiledPattern.ALL_CLASS_CONTENT_VAR_NAME_KEY, name); |
| MatchOptions options = myCompilingVisitor.getContext().getOptions(); |
| if (options.getVariableConstraint(name) == null) { |
| pattern.createSubstitutionHandler(name, name, false, 0, Integer.MAX_VALUE, true); |
| MatchVariableConstraint constraint = new MatchVariableConstraint(true); |
| constraint.setName(name); |
| constraint.setMinCount(0); |
| constraint.setMaxCount(Integer.MAX_VALUE); |
| options.addVariableConstraint(constraint); |
| } |
| } |
| } |
| |
| private SubstitutionHandler createAndSetSubstitutionHandlerFromReference(final PsiElement expr, final String referenceText, |
| boolean classQualifier) { |
| final SubstitutionHandler substitutionHandler = |
| new SubstitutionHandler("__" + referenceText.replace('.', '_'), false, classQualifier ? 0 : 1, 1, false); |
| substitutionHandler.setPredicate(new RegExpPredicate(referenceText.replaceAll("\\.", "\\\\."), true, null, false, false)); |
| myCompilingVisitor.getContext().getPattern().setHandler(expr, substitutionHandler); |
| return substitutionHandler; |
| } |
| |
| @Override |
| public void visitExpressionStatement(PsiExpressionStatement expr) { |
| myCompilingVisitor.handle(expr); |
| |
| super.visitExpressionStatement(expr); |
| |
| final PsiElement child = expr.getLastChild(); |
| if (!(child instanceof PsiJavaToken) && !(child instanceof PsiComment)) { |
| // search for expression or symbol |
| final PsiElement reference = expr.getFirstChild(); |
| MatchingHandler referenceHandler = myCompilingVisitor.getContext().getPattern().getHandler(reference); |
| |
| if (referenceHandler instanceof SubstitutionHandler && |
| (reference instanceof PsiReferenceExpression) |
| ) { |
| // symbol |
| myCompilingVisitor.getContext().getPattern().setHandler(expr, referenceHandler); |
| referenceHandler.setFilter( |
| SymbolNodeFilter.getInstance() |
| ); |
| |
| myCompilingVisitor.setHandler(expr, new SymbolHandler((SubstitutionHandler)referenceHandler)); |
| } |
| else if (reference instanceof PsiLiteralExpression) { |
| MatchingHandler handler = new ExpressionHandler(); |
| myCompilingVisitor.setHandler(expr, handler); |
| handler.setFilter(ConstantFilter.getInstance()); |
| } |
| else { |
| // just expression |
| MatchingHandler handler; |
| myCompilingVisitor.setHandler(expr, handler = new ExpressionHandler()); |
| |
| handler.setFilter(ExpressionFilter.getInstance()); |
| } |
| } |
| else if (expr.getExpression() instanceof PsiReferenceExpression && |
| (myCompilingVisitor.getContext().getPattern().isRealTypedVar(expr.getExpression()))) { |
| // search for statement |
| final MatchingHandler exprHandler = myCompilingVisitor.getContext().getPattern().getHandler(expr); |
| if (exprHandler instanceof SubstitutionHandler) { |
| SubstitutionHandler handler = (SubstitutionHandler)exprHandler; |
| handler.setFilter(new StatementFilter()); |
| handler.setMatchHandler(new StatementHandler()); |
| } |
| } |
| } |
| |
| @Override |
| public void visitElement(PsiElement element) { |
| myCompilingVisitor.handle(element); |
| super.visitElement(element); |
| } |
| |
| |
| private void handleReference(PsiJavaCodeReferenceElement reference) { |
| handleReferenceText(reference.getReferenceName(), myCompilingVisitor.getContext()); |
| } |
| |
| private static void handleReferenceText(String refname, CompileContext compileContext) { |
| if (refname == null) return; |
| |
| if (compileContext.getPattern().isTypedVar(refname)) { |
| SubstitutionHandler handler = (SubstitutionHandler)compileContext.getPattern().getHandler(refname); |
| RegExpPredicate predicate = MatchingHandler.getSimpleRegExpPredicate(handler); |
| if (!GlobalCompilingVisitor.isSuitablePredicate(predicate, handler)) { |
| return; |
| } |
| |
| refname = predicate.getRegExp(); |
| |
| if (handler.isStrictSubtype() || handler.isSubtype()) { |
| final OptimizingSearchHelper searchHelper = compileContext.getSearchHelper(); |
| if (addDescendantsOf(refname, handler.isSubtype(), searchHelper, compileContext)) { |
| searchHelper.endTransaction(); |
| } |
| |
| return; |
| } |
| } |
| |
| GlobalCompilingVisitor.addFilesToSearchForGivenWord(refname, true, GlobalCompilingVisitor.OccurenceKind.CODE, compileContext); |
| } |
| |
| |
| public static boolean addDescendantsOf(final String refname, final boolean subtype, OptimizingSearchHelper searchHelper, CompileContext context) { |
| final List<PsiClass> classes = buildDescendants(refname, subtype, searchHelper, context); |
| |
| for (final PsiClass aClass : classes) { |
| if (aClass instanceof PsiAnonymousClass) { |
| searchHelper.addWordToSearchInCode(((PsiAnonymousClass)aClass).getBaseClassReference().getReferenceName()); |
| } |
| else { |
| searchHelper.addWordToSearchInCode(aClass.getName()); |
| } |
| } |
| |
| return classes.size() > 0; |
| } |
| |
| private static List<PsiClass> buildDescendants(String className, |
| boolean includeSelf, |
| OptimizingSearchHelper searchHelper, |
| CompileContext context) { |
| if (!searchHelper.doOptimizing()) return Collections.emptyList(); |
| final SearchScope scope = context.getOptions().getScope(); |
| if (!(scope instanceof GlobalSearchScope)) return Collections.emptyList(); |
| |
| final PsiShortNamesCache cache = PsiShortNamesCache.getInstance(context.getProject()); |
| final PsiClass[] classes = cache.getClassesByName(className, (GlobalSearchScope)scope); |
| final List<PsiClass> results = new ArrayList<PsiClass>(); |
| |
| final PsiElementProcessor<PsiClass> processor = new PsiElementProcessor<PsiClass>() { |
| public boolean execute(@NotNull PsiClass element) { |
| results.add(element); |
| return true; |
| } |
| |
| }; |
| |
| for (PsiClass aClass : classes) { |
| ClassInheritorsSearch.search(aClass, scope, true).forEach(new PsiElementProcessorAdapter<PsiClass>(processor)); |
| } |
| |
| if (includeSelf) { |
| Collections.addAll(results, classes); |
| } |
| |
| return results; |
| } |
| |
| |
| @Override |
| public void visitCodeBlock(PsiCodeBlock block) { |
| myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() + 1); |
| MatchingStrategy strategy = null; |
| |
| for (PsiElement el = block.getFirstChild(); el != null; el = el.getNextSibling()) { |
| if (GlobalCompilingVisitor.getFilter().accepts(el)) { |
| if (el instanceof PsiWhiteSpace) { |
| myCompilingVisitor.addLexicalNode(el); |
| } |
| } |
| else { |
| el.accept(this); |
| if (myCompilingVisitor.getCodeBlockLevel() == 1) { |
| MatchingStrategy newstrategy = findStrategy(el); |
| final MatchingHandler matchingHandler = myCompilingVisitor.getContext().getPattern().getHandler(el); |
| myCompilingVisitor.getContext().getPattern().setHandler(el, new TopLevelMatchingHandler(matchingHandler)); |
| |
| if (strategy == null || (strategy instanceof JavaDocMatchingStrategy)) { |
| strategy = newstrategy; |
| } |
| else { |
| if (strategy.getClass() != newstrategy.getClass()) { |
| if (!(strategy instanceof CommentMatchingStrategy)) { |
| throw new UnsupportedPatternException(SSRBundle.message("different.strategies.for.top.level.nodes.error.message")); |
| } |
| strategy = newstrategy; |
| } |
| } |
| } |
| } |
| } |
| |
| if (myCompilingVisitor.getCodeBlockLevel() == 1) { |
| if (strategy == null) { |
| // this should happen only for error patterns |
| strategy = ExprMatchingStrategy.getInstance(); |
| } |
| myCompilingVisitor.getContext().getPattern().setStrategy(strategy); |
| } |
| myCompilingVisitor.setCodeBlockLevel(myCompilingVisitor.getCodeBlockLevel() - 1); |
| } |
| |
| private MatchingStrategy findStrategy(PsiElement el) { |
| // identify matching strategy |
| final MatchingHandler handler = myCompilingVisitor.getContext().getPattern().getHandler(el); |
| |
| //if (handler instanceof SubstitutionHandler) { |
| // final SubstitutionHandler shandler = (SubstitutionHandler) handler; |
| if (handler.getFilter() instanceof SymbolNodeFilter || |
| handler.getFilter() instanceof TypedSymbolNodeFilter |
| ) { |
| return SymbolMatchingStrategy.getInstance(); |
| } |
| //} |
| |
| if (el instanceof PsiDocComment) { |
| return JavaDocMatchingStrategy.getInstance(); |
| } |
| else if (el instanceof PsiComment) { |
| return CommentMatchingStrategy.getInstance(); |
| } |
| |
| return ExprMatchingStrategy.getInstance(); |
| } |
| |
| private static boolean needsSupers(final PsiElement element, final MatchingHandler handler) { |
| if (element.getParent() instanceof PsiClass && |
| handler instanceof SubstitutionHandler |
| ) { |
| final SubstitutionHandler handler2 = (SubstitutionHandler)handler; |
| |
| return (handler2.isStrictSubtype() || handler2.isSubtype()); |
| } |
| return false; |
| } |
| } |