diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/CategorySearchTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/CategorySearchTests.java index 0248d79691..25c8e4db66 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/CategorySearchTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/CategorySearchTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2020 the original author or authors. + * Copyright 2009-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,77 +36,74 @@ public final class CategorySearchTests extends SearchTestSuite { //@formatter:off - private static String CATEGORY_DEFN = + private static String CATEGORY_CLASSES = + "class CatTarget {\n" + + " CatTarget self\n" + + "}\n" + "class Cat {\n" + - " static String doNothing(CatTarget e, msg) {\n" + + " static String printMessage(CatTarget e, msg) {\n" + " print msg\n" + " }\n" + "}\n" + - "class CatTarget {\n" + - " CatTarget self\n" + - "}\n" + "class Cat2 {\n" + - " static String doNothing2(CatTarget e, msg) {\n" + + " static String printMessage2(CatTarget e, msg) {\n" + " print msg\n" + " }\n" + + "}\n" + + "class Cat3 extends Cat {\n" + "}"; private static String SIMPLE_CATEGORY = "use (Cat) {\n" + - " new CatTarget().doNothing 'jello'\n" + + " new CatTarget().printMessage 'jello'\n" + " def x = new CatTarget()\n" + - " x.doNothing 'jello'\n" + + " x.printMessage 'jello'\n" + " x.self = x\n" + - " x.doNothing 'jello'\n" + - " Cat.doNothing x, 'jello'\n" + + " x.printMessage 'jello'\n" + + " Cat.printMessage x, 'jello'\n" + "}"; private static String CATEGORY_WITH_SUBTYPE = "class Sub extends CatTarget { }\n" + "use (Cat) {\n" + - " new Sub().doNothing 'jello'\n" + + " new Sub().printMessage 'jello'\n" + " def x = new Sub()\n" + - " x.doNothing 'jello'\n" + + " x.printMessage 'jello'\n" + " x.self = x\n" + - " x.doNothing 'jello'\n" + - " Cat.doNothing x, 'jello'\n" + + " x.printMessage 'jello'\n" + + " Cat.printMessage x, 'jello'\n" + "}"; private static String CATEGORY_ASSIGNED = "def y = Cat\n" + "use (y) {\n" + - " new CatTarget().doNothing 'jello'\n" + + " new CatTarget().printMessage 'jello'\n" + " def x = new CatTarget()\n" + - " x.doNothing 'jello'\n" + + " x.printMessage 'jello'\n" + " x.self = x\n" + - " x.doNothing 'jello'\n" + - " y.doNothing x, 'jello'\n" + + " x.printMessage 'jello'\n" + + " y.printMessage x, 'jello'\n" + "}"; private static String CATEGORY_MULTIPLE_OUTER = "use (Cat) { use (Cat2) {\n" + - " new CatTarget().doNothing 'jello'\n" + + " new CatTarget().printMessage 'jello'\n" + " def x = new CatTarget()\n" + - " x.doNothing 'jello'\n" + + " x.printMessage 'jello'\n" + " x.self = x\n" + - " x.doNothing 'jello'\n" + - " Cat.doNothing x, 'jello'\n" + + " x.printMessage 'jello'\n" + + " Cat.printMessage x, 'jello'\n" + "} }"; private static String CATEGORY_MULTIPLE_INNER = "use (Cat2) { use (Cat) {\n" + - " new CatTarget().doNothing 'jello'\n" + + " new CatTarget().printMessage 'jello'\n" + " def x = new CatTarget()\n" + - " x.doNothing 'jello'\n" + + " x.printMessage 'jello'\n" + " x.self = x\n" + - " x.doNothing 'jello'\n" + - " Cat.doNothing x, 'jello'\n" + + " x.printMessage 'jello'\n" + + " Cat.printMessage x, 'jello'\n" + "} }"; - - private static String NO_CATEGORY = - "use (Cat) {\n" + - "}\n" + - "new CatTarget().doNothing 'jello'\n"; //@formatter:on @Test @@ -136,7 +133,15 @@ public void testCategorySearch5() throws Exception { @Test public void testCategorySearch6() throws Exception { - doCategorySearchTest(NO_CATEGORY, 0); + doCategorySearchTest("use (Cat) {}\n" + + "new CatTarget().printMessage('')\n", 0); + } + + @Test + public void testCategorySearch7() throws Exception { + doCategorySearchTest("use (Cat3) {\n" + + " new CatTarget().printMessage('')\n" + + "}", 1); } //-------------------------------------------------------------------------- @@ -146,12 +151,12 @@ private void doCategorySearchTest(final String contents, final int numMatches) t } private List findMatches(final String contents) throws JavaModelException { - GroovyCompilationUnit catUnit = createUnit("Cat", CATEGORY_DEFN); - GroovyCompilationUnit unit = createUnit("Other", contents); + GroovyCompilationUnit catUnit = createUnit("Cat", CATEGORY_CLASSES); + GroovyCompilationUnit unit = createUnit("Script", contents); expectingNoProblems(); - IMethod searchFor = (IMethod) catUnit.getElementAt(CATEGORY_DEFN.indexOf("doNothing")); - assertEquals("Wrong IJavaElement found: " + searchFor, "doNothing", searchFor.getElementName()); + IMethod searchFor = (IMethod) catUnit.getElementAt(CATEGORY_CLASSES.indexOf("printMessage")); + assertEquals("Wrong IJavaElement found: " + searchFor, "printMessage", searchFor.getElementName()); return search(SearchPattern.createPattern(searchFor, IJavaSearchConstants.REFERENCES), unit); } @@ -159,12 +164,12 @@ private void checkMatches(final List matches, final int nExpected, assertEquals("Wrong number of matches found:\n" + toString(matches), nExpected, matches.size()); if (nExpected > 0) { Iterator it = matches.iterator(); - Pattern p = Pattern.compile("doNothing"); + Pattern p = Pattern.compile("printMessage"); Matcher m = p.matcher(contents); while (m.find()) { SearchMatch match = it.next(); assertEquals("Wrong starting location for " + toString(match), m.start(), match.getOffset()); - assertEquals("Wrong length for " + toString(match), "doNothing".length(), match.getLength()); + assertEquals("Wrong length for " + toString(match), "printMessage".length(), match.getLength()); } } } diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/CategoryTypeLookup.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/CategoryTypeLookup.java index 10c11bea3c..4595d707e3 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/CategoryTypeLookup.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/CategoryTypeLookup.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 the original author or authors. + * Copyright 2009-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,7 +62,7 @@ public TypeLookupResult lookupType(final Expression node, final VariableScope sc if (isMethodPointer || scope.isMethodCall()) { for (ClassNode category : scope.getCategoryNames()) { - for (MethodNode method : category.getMethods(simpleName)) { + for (MethodNode method : category.getDeclaredMethods(simpleName)) { if (isCompatibleCategoryMethod(method, selfType, scope)) { candidates.add(method); } @@ -74,7 +74,7 @@ public TypeLookupResult lookupType(final Expression node, final VariableScope sc String methodName = kind.createAccessorName(simpleName); if (methodName != null) { for (ClassNode category : scope.getCategoryNames()) { - for (MethodNode method : category.getMethods(methodName)) { + for (MethodNode method : category.getDeclaredMethods(methodName)) { if (kind.isAccessorKind(method, true) && isCompatibleCategoryMethod(method, selfType, scope) && // GROOVY-5245: isPropName() methods cannot be used for bean-style property expressions (kind != AccessorSupport.ISSER || isDefaultGroovyMethod(method, scope) || isDefaultGroovyStaticMethod(method, scope) || GroovyUtils.getGroovyVersion().getMajor() > 3)) { diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java index 5e10a9bcc9..ff89205348 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java @@ -281,6 +281,11 @@ public Set getCategoryNames() { if (parent.isCategoryBeingDeclared()) { categories = new LinkedHashSet<>(categories); categories.add(parent.categoryBeingDeclared); + for (ClassNode superClass = parent.categoryBeingDeclared.getSuperClass(); + superClass != OBJECT_CLASS_NODE && superClass != null; + superClass = superClass.getSuperClass()) { + categories.add(superClass); + } } } else { categories = scopeNode.getNodeMetaData(DefaultGroovyMethods.class, key -> { diff --git a/ide-test/org.codehaus.groovy.eclipse.codeassist.test/src/org/codehaus/groovy/eclipse/codeassist/tests/DefaultGroovyMethodCompletionTests.groovy b/ide-test/org.codehaus.groovy.eclipse.codeassist.test/src/org/codehaus/groovy/eclipse/codeassist/tests/DefaultGroovyMethodCompletionTests.groovy index de7f22eea6..92b729eea3 100644 --- a/ide-test/org.codehaus.groovy.eclipse.codeassist.test/src/org/codehaus/groovy/eclipse/codeassist/tests/DefaultGroovyMethodCompletionTests.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.codeassist.test/src/org/codehaus/groovy/eclipse/codeassist/tests/DefaultGroovyMethodCompletionTests.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 the original author or authors. + * Copyright 2009-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -320,6 +320,13 @@ final class DefaultGroovyMethodCompletionTests extends CompletionTestSuite { proposalExists(proposals, 'findAll() : List', 1) // not Collection } + @Test + void testNoSuper() { + ICompletionProposal[] proposals = createProposalsAtOffset('void m(InputStream s){s.c}\n', 25) + proposalExists(proposals, 'closeQuietly()', 0) // from DefaultGroovyMethodsSupport + proposalExists(proposals, 'withCloseable', 1) + } + @Test void testNoExtras() { ICompletionProposal[] proposals = createProposalsAtOffset('[].stream().collect()\n', 20) diff --git a/ide/org.codehaus.groovy.eclipse.codeassist/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java b/ide/org.codehaus.groovy.eclipse.codeassist/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java index 97e28fc15e..ba0f9224bc 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist/src/org/codehaus/groovy/eclipse/codeassist/creators/CategoryProposalCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 the original author or authors. + * Copyright 2009-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,7 +71,7 @@ public List findAllProposals(final ClassNode selfType, final Se List proposals = new ArrayList<>(); for (ClassNode category : categories) { boolean isDefaultCategory = isDefaultCategory(category); - for (MethodNode method : getAllMethods(category, null)) { + for (MethodNode method : category.getMethods()) { // check for DGMs filtered by deprecation or user preference if (isDefaultCategory && (GroovyUtils.isDeprecated(method) || filter.isFiltered(method))) { continue;