SRR: easier searching for methods

This commit is contained in:
Bas Leijdekkers
2015-10-06 17:08:48 +02:00
parent e01588f958
commit 7aa7a0b082
6 changed files with 69 additions and 41 deletions
@@ -46,7 +46,7 @@ class JavaPredefinedConfigurations {
// Class based
createSearchTemplateInfo(
SSRBundle.message("predefined.configuration.methods.of.the.class"),
"class '_Class { \n '_ReturnType+ 'MethodName+('_ParameterType* '_Parameter*);\n}",
"'_ReturnType+ '_MethodName+('_ParameterType* '_Parameter*);",
CLASS_TYPE
),
createSearchTemplateInfo(
@@ -126,7 +126,7 @@ class JavaPredefinedConfigurations {
),
createSearchTemplateInfo(
SSRBundle.message("predefined.configuration.class.instance.initialization.blocks"),
"class '_A {\n @Modifier(\"Instance\") {\n 'Statement*;\n }\n}",
"@Modifier(\"Instance\") {\n '_Statement*;\n}",
CLASS_TYPE
),
createSearchTemplateInfo(
@@ -161,7 +161,7 @@ class JavaPredefinedConfigurations {
// Generics
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.classes"),"class 'GenericClass<'_TypeParameter+> {} ", GENERICS_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.methods"),"class '_Class {\n <'_TypeParameter+> '_Type+ 'Method+('_ParameterType* '_ParameterDcl*);\n}", GENERICS_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.methods"),"<'_TypeParameter+> '_Type+ '_Method+('_ParameterType* '_ParameterDcl*);", GENERICS_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.typed.symbol"),"'Symbol <'_GenericArgument+>", GENERICS_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.generic.casts"),"( '_Type <'_GenericArgument+> ) '_Expr", GENERICS_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.type.var.substitutions.in.intanceof.with.generic.types"),"'_Expr instanceof '_Type <'Substitutions+> ", GENERICS_TYPE),
@@ -171,7 +171,7 @@ class JavaPredefinedConfigurations {
// Add comments and metadata
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.comments"),"/* 'CommentContent */", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.class"),"/** @'_Tag+ '_TagValue* */\nclass '_Class {\n}", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.methods"),"class '_Class {\n /** @'_Tag+ '_TagValue* */\n '_Type+ 'Method+('_ParameterType* '_ParameterDcl*);\n}", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.methods"),"/** @'_Tag+ '_TagValue* */\n'_Type+ '_Method+('_ParameterType* '_ParameterDcl*);", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.annotated.fields"),"class '_Class {\n /** @'_Tag+ '_TagValue* */\n '_Type+ 'Field+ = '_Init*;\n}", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.javadoc.tags"),"/** @'Tag+ '_TagValue* */", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.xdoclet.metadata"),"/** @'Tag \n '_Property+\n*/", METADATA_TYPE),
@@ -186,16 +186,10 @@ class JavaPredefinedConfigurations {
" '_FieldType+ 'FieldName+ = '_FieldInitial*;\n" +
"}", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.annotated.methods"),
"class '_Class {\n" +
" @'_Annotation+( )\n" +
" '_MethodType+ 'MethodName+('_ParameterType* '_ParameterName*);\n" +
"}", METADATA_TYPE),
"@'_Annotation+( )\n'_MethodType+ '_MethodName+('_ParameterType* '_ParameterName*);", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.not.annotated.methods"),
"class '_Class {\n" +
" @'_Annotation{0,0}\n" +
" '_MethodType+ 'MethodName+('_ParameterType* '_ParameterName*);\n" +
"}", METADATA_TYPE),
"@'_Annotation{0,0}\n'_MethodType+ '_MethodName+('_ParameterType* '_ParameterName*);", METADATA_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.annotation.declarations"),
"@interface 'Interface {}", METADATA_TYPE),
@@ -268,16 +262,15 @@ class JavaPredefinedConfigurations {
" return '_Instance;\n" +
" }\n"+
"}",MISC_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.similar.methods.structure"),"class '_Class {\n" +
" '_RetType 'Method+('_ParameterType* '_Parameter) throws 'ExceptionType {\n" +
" try {\n" +
" '_OtherStatements+;\n" +
" } catch('_SomeException '_ExceptionDcl) {\n" +
" '_CatchStatement*;\n" +
" throw new 'ExceptionType('_ExceptionConstructorArgs*);\n" +
" }\n" +
" }\n" +
"}",MISC_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.similar.methods.structure"),
"'_RetType '_Method+('_ParameterType* '_Parameter) throws 'ExceptionType {\n" +
" try {\n" +
" '_OtherStatements+;\n" +
" } catch('_SomeException '_ExceptionDcl) {\n" +
" '_CatchStatement*;\n" +
" throw new 'ExceptionType('_ExceptionConstructorArgs*);\n" +
" }\n" +
"}", MISC_TYPE),
createSearchTemplateInfo(SSRBundle.message("predefined.configuration.bean.info.classes"),"class 'A implements '_:*java\\.beans\\.BeanInfo {\n" +
"}",MISC_TYPE),
@@ -194,9 +194,9 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
if (physical) {
throw new UnsupportedOperationException(getClass() + " cannot create physical PSI");
}
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
if (context == PatternTreeContext.Block) {
PsiElement element = elementFactory.createStatementFromText("{\n" + text + "\n}", null);
final PsiElement element = elementFactory.createStatementFromText("{\n" + text + "\n}", null);
final PsiElement[] children = ((PsiBlockStatement)element).getCodeBlock().getChildren();
final int extraChildCount = 4;
@@ -204,6 +204,14 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
PsiElement[] result = new PsiElement[children.length - extraChildCount];
final int extraChildStart = 2;
System.arraycopy(children, extraChildStart, result, 0, children.length - extraChildCount);
if (shouldTryClassPattern(result)) {
final PsiElement[] classPattern =
createPatternTree(text, PatternTreeContext.Class, fileType, language, contextName, extension, project, false);
if (classPattern.length == 1) {
result = classPattern;
}
}
return result;
}
else {
@@ -211,8 +219,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
}
}
else if (context == PatternTreeContext.Class) {
PsiElement element = elementFactory.createStatementFromText("class A {\n" + text + "\n}", null);
PsiClass clazz = (PsiClass)((PsiDeclarationStatement)element).getDeclaredElements()[0];
final PsiClass clazz = elementFactory.createClassFromText(text, null);
PsiElement startChild = clazz.getLBrace();
if (startChild != null) startChild = startChild.getNextSibling();
@@ -220,11 +227,12 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
if (endChild != null) endChild = endChild.getPrevSibling();
if (startChild == endChild) return PsiElement.EMPTY_ARRAY; // nothing produced
final PsiCodeBlock codeBlock = elementFactory.createCodeBlock();
final List<PsiElement> result = new ArrayList<PsiElement>(3);
assert startChild != null;
for (PsiElement el = startChild.getNextSibling(); el != endChild && el != null; el = el.getNextSibling()) {
if (el instanceof PsiErrorElement) continue;
result.add(el);
result.add(codeBlock.add(el));
}
return PsiUtilCore.toPsiElementArray(result);
@@ -234,6 +242,19 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
}
}
private static boolean shouldTryClassPattern(PsiElement[] result) {
if (result.length == 3 && PsiModifier.STATIC.equals(result[0].getText()) && result[1] instanceof PsiWhiteSpace &&
result[2] instanceof PsiBlockStatement) {
// looks like static initializer
return true;
}
else if (result.length > 1 && result[0] instanceof PsiDeclarationStatement && !result[0].getText().endsWith(";")) {
// might be method
return true;
}
return false;
}
@NotNull
@Override
public Editor createEditor(@NotNull SearchContext searchContext,
@@ -350,7 +350,7 @@ public class JavaMatchingVisitor extends JavaElementVisitor {
}
// check if element is declared in current class (not in ancestors)
return element.getContainingClass() == myClazz;
return myClazz == null || element.getContainingClass() == myClazz;
}
@Override
@@ -136,19 +136,6 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor {
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);
@@ -2403,5 +2403,14 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
" System.out.println();\n" +
" }\n" +
"}\n", replacer.testReplace(in, what, by, options));
final String what2 = "void '_a:[regex( test.* )]();";
final String by2 = "@org.junit.Test void $a$();";
assertEquals("class A extends TestCase {\n" +
" @org.junit.Test void testOne(){\n" +
" System.out.println();\n" +
" }\n" +
"}\n",
replacer.testReplace(in, what2, by2, options));
}
}
@@ -3327,4 +3327,22 @@ public class StructuralSearchTest extends StructuralSearchTestCase {
"}";
assertEquals("find incomplete code", 1, findMatchesCount(source2, "'_a '_b{2,100};"));
}
public void testFindWithSimpleMemberPattern() {
String source = "class X {" +
" static {}" +
" static {}" +
" static {" +
" System.out.println();" +
" }" +
" void one() {}" +
" void two() {" +
" System.out.println();" +
" }" +
"}";
assertEquals("find with simple method pattern", 2, findMatchesCount(source, "void '_a();"));
assertEquals("find with simple method pattern 2", 1, findMatchesCount(source, "void one();"));
assertEquals("find with simple static initializer pattern", 3, findMatchesCount(source, "static { '_statement*;}"));
}
}