diff --git a/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyCompilationUnitDeclaration.java b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyCompilationUnitDeclaration.java index 3ef269630a..f04d39daf0 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyCompilationUnitDeclaration.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/internal/compiler/ast/GroovyCompilationUnitDeclaration.java @@ -1164,7 +1164,7 @@ private void createTypeDeclarations(ModuleNode moduleNode) { allocation.sourceStart = isEnum ? typeDeclaration.sourceStart : typeDeclaration.sourceStart - 4; // approx. offset of "new" allocation.sourceEnd = typeDeclaration.bodyEnd; // TODO: allocation.typeArguments = something - allocation.type = typeDeclaration.superclass; + if (!isEnum) allocation.type = typeDeclaration.superclass; } } else { typeDeclarations.add(typeDeclaration); @@ -1242,11 +1242,12 @@ private FieldDeclaration[] createFieldDeclarations(ClassNode classNode, boolean fieldDeclaration.annotations = createAnnotations(fieldNode.getAnnotations()); if (!isEnumField) { fieldDeclaration.modifiers = getModifiers(fieldNode); - fieldDeclaration.type = createTypeReferenceForClassNode(fieldNode.getType()); + fieldDeclaration.initializer = fieldNode.getInitialExpression(); if (fieldNode.isStatic() && fieldNode.isFinal() && fieldNode.getInitialExpression() instanceof ConstantExpression) { // this needs to be set for static finals to correctly determine constant status fieldDeclaration.initialization = createConstantExpression((ConstantExpression) fieldNode.getInitialExpression()); } + fieldDeclaration.type = createTypeReferenceForClassNode(fieldNode.getType()); if (anonymousLocations != null && fieldNode.getInitialExpression() != null) { fieldNode.getInitialExpression().visit(new CodeVisitorSupport() { @@ -1260,7 +1261,6 @@ public void visitConstructorCallExpression(ConstructorCallExpression call) { }); } } - fieldDeclaration.initializer = fieldNode.getInitialExpression(); fixupSourceLocationsForFieldDeclaration(fieldDeclaration, fieldNode, isEnumField); fieldDeclarations.add(fieldDeclaration); diff --git a/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/model/GroovyProjectFacade.java b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/model/GroovyProjectFacade.java index 9de317598f..001239bc10 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/model/GroovyProjectFacade.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/model/GroovyProjectFacade.java @@ -15,11 +15,6 @@ */ package org.codehaus.jdt.groovy.model; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.FieldNode; @@ -27,29 +22,20 @@ import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.ModuleNode; import org.codehaus.groovy.ast.Parameter; -import org.codehaus.groovy.ast.expr.DeclarationExpression; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.groovy.core.util.GroovyUtils; import org.eclipse.jdt.internal.core.JavaElement; -import org.eclipse.jdt.internal.core.LocalVariable; import org.eclipse.jdt.internal.core.ResolvedSourceField; import org.eclipse.jdt.internal.core.ResolvedSourceMethod; import org.eclipse.jdt.internal.core.ResolvedSourceType; -import org.eclipse.jdt.internal.core.SourceType; import org.eclipse.jdt.internal.core.util.Util; public class GroovyProjectFacade { @@ -74,72 +60,24 @@ public IJavaProject getProject() { return project; } - /** - * best effort to map a groovy node to a JavaElement - * If the groovy element is not a declaration (eg- an expression or statement) - * returns instead the closest enclosing element that can be converted - * to an IJavaElement - * - * If node is a local variable declaration, then returns a LocalVariable - */ - public IJavaElement groovyNodeToJavaElement(ASTNode node, IFile file) { - ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file); - if (!(unit instanceof GroovyCompilationUnit)) { - // can't go any further, just return the unit instead - Util.log(IStatus.WARNING, "Trying to get a groovy element from a non-groovy file: " + file.getName()); - return unit; - } - - try { - int start = node.getStart(); - IJavaElement elt = unit.getElementAt(start); - if (node instanceof DeclarationExpression) { - String var = ((DeclarationExpression) node).getVariableExpression().getName(); - int end = start + var.length() - 1; - String sig = Signature.createTypeSignature(((DeclarationExpression) node).getVariableExpression().getType().getName(), false); - - return new LocalVariable((JavaElement) elt, var, start, end, start, end, sig, null, 0, false); - } else { - return elt; - } - } catch (Exception e) { - Util.log(e, "Error converting from Groovy Element to Java Element: " + node.getText()); - } - return null; - } - + @Deprecated // use org.codehaus.jdt.groovy.model.JavaCoreUtil.findType(String, IJavaElement) public IType groovyClassToJavaType(ClassNode node) { if (parent != null && parent.getFullyQualifiedName().equals(node.getName())) { return parent; } - try { - ClassNode toLookFor = node; - if (GroovyUtils.isAnonymous(node)) { - toLookFor = node.getOuterClass(); - IType enclosing = groovyClassToJavaType(toLookFor); - if (enclosing != null && !enclosing.isBinary()) { - return fakeAnonymousInnerClass(enclosing, (InnerClassNode) node); - } else { - // if the 'enclosing' is binary we may assume this one is also binary, - // so we should just be able to look for it with the type name (including the $ etc.) - return project.findType(node.getName(), (IProgressMonitor) null); - } - } - - // GRECLIPSE-800: ensure that inner class nodes are handled properly - String name = toLookFor.getName().replace('$', '.'); - IType type = project.findType(name, (IProgressMonitor) null); - if (type != null && toLookFor != node) { - type = type.getType("", 1); - if (!type.exists()) { - type = null; - } + IType type = null; + if (GroovyUtils.isAnonymous(node)) { + type = JavaCoreUtil.findType(node.getOuterClass().getName(), project); + if (type != null && type.exists() && !type.isBinary()) { + type = fakeAnonymousInnerClass(type, (InnerClassNode) node); + } else { + type = null; } - return type; - } catch (JavaModelException e) { - Util.log(e, "Error converting from Groovy Element to Java Element: " + node.getName()); - return null; } + if (type == null) { + type = JavaCoreUtil.findType(node.getName(), project); + } + return type; } private IType fakeAnonymousInnerClass(IType outer, final InnerClassNode inner) { @@ -238,37 +176,6 @@ public Object getElementInfo() throws JavaModelException { }; } - GroovyCompilationUnit groovyModuleToCompilationUnit(ModuleNode node) { - List classes = node.getClasses(); - ClassNode classNode = !classes.isEmpty() ? (ClassNode) classes.get(0) : null; - if (classNode != null) { - IType type = groovyClassToJavaType(classNode); - if (type instanceof SourceType) { - return (GroovyCompilationUnit) type.getCompilationUnit(); - } - } - Util.log(IStatus.WARNING, "Trying to get GroovyCompilationUnit for non-groovy module: " + node.getDescription()); - return null; - } - - /** - * If this fully qualified name is in a groovy file, then return the - * ClassNode. - * - * If this is not a groovy file, then return null - */ - public ClassNode getClassNodeForName(String name) { - try { - IType type = project.findType(name, (IProgressMonitor) null); - if (type instanceof SourceType) { - return javaTypeToGroovyClass(type); - } - } catch (JavaModelException e) { - Util.log(e); - } - return null; - } - private Parameter[] getParametersForTypes(String[] signatures) { int n = signatures.length; Parameter[] parameters = new Parameter[n]; @@ -278,60 +185,7 @@ private Parameter[] getParametersForTypes(String[] signatures) { return parameters; } - private static ClassNode javaTypeToGroovyClass(String signature) { - int dims = Signature.getArrayCount(signature); // TODO: handle generics types - String type = Signature.toString(Signature.getTypeErasure(signature.substring(dims))); - - ClassNode node = ClassHelper.make(type); - while (dims-- > 0) { - node = node.makeArray(); - } - return node; - } - - private static ClassNode javaTypeToGroovyClass(IType type) { - ICompilationUnit unit = type.getCompilationUnit(); - if (unit instanceof GroovyCompilationUnit) { - ModuleNode module = ((GroovyCompilationUnit) unit).getModuleNode(); - List classes = module.getClasses(); - for (ClassNode classNode : classes) { - if (classNode.getNameWithoutPackage().equals(type.getElementName())) { - return classNode; - } - } - } - return null; - } - - public List findAllRunnableTypes() throws JavaModelException { - final List results = new ArrayList<>(); - IPackageFragmentRoot[] roots = project.getAllPackageFragmentRoots(); - for (IPackageFragmentRoot root : roots) { - if (!root.isReadOnly()) { - IJavaElement[] children = root.getChildren(); - for (IJavaElement child : children) { - if (child.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { - ICompilationUnit[] units = ((IPackageFragment) child).getCompilationUnits(); - for (ICompilationUnit unit : units) { - results.addAll(findAllRunnableTypes(unit)); - } - } - } - } - } - return results; - } - - public static List findAllRunnableTypes(ICompilationUnit unit) throws JavaModelException { - List results = new LinkedList<>(); - IType[] types = unit.getAllTypes(); - for (IType type : types) { - if (hasRunnableMain(type)) { - results.add(type); - } - } - return results; - } + //-------------------------------------------------------------------------- public static boolean hasRunnableMain(IType type) { try { @@ -369,32 +223,7 @@ private static boolean hasAppropriateArrayArgsForMain(final String[] params) { return (name.equals(typeName)) && (qual == null || qual.isEmpty() || "java.lang".equals(qual)); } - public List findAllScripts() throws JavaModelException { - final List results = new ArrayList<>(); - IPackageFragmentRoot[] roots = project.getAllPackageFragmentRoots(); - for (IPackageFragmentRoot root : roots) { - if (!root.isReadOnly()) { - IJavaElement[] children = root.getChildren(); - for (IJavaElement child : children) { - if (child.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { - ICompilationUnit[] units = ((IPackageFragment) child).getCompilationUnits(); - for (ICompilationUnit unit : units) { - if (unit instanceof GroovyCompilationUnit) { - for (IType type : unit.getTypes()) { - if (isGroovyScript(type)) { - results.add(type); - } - } - } - } - } - } - } - } - return results; - } - - public boolean isGroovyScript(IType type) { + public static boolean isGroovyScript(IType type) { ClassNode node = javaTypeToGroovyClass(type); if (node != null) { return node.isScript(); @@ -402,18 +231,27 @@ public boolean isGroovyScript(IType type) { return false; } - public boolean isGroovyScript(ICompilationUnit unit) { + private static ClassNode javaTypeToGroovyClass(IType type) { + ICompilationUnit unit = type.getCompilationUnit(); if (unit instanceof GroovyCompilationUnit) { - GroovyCompilationUnit gunit = (GroovyCompilationUnit) unit; - ModuleNode module = gunit.getModuleNode(); - if (module != null) { - for (ClassNode clazz : (Iterable) module.getClasses()) { - if (clazz.isScript()) { - return true; - } + ModuleNode module = ((GroovyCompilationUnit) unit).getModuleNode(); + for (ClassNode classNode : module.getClasses()) { + if (classNode.getNameWithoutPackage().equals(type.getElementName())) { + return classNode; } } } - return false; + return null; + } + + private static ClassNode javaTypeToGroovyClass(String signature) { + int dims = Signature.getArrayCount(signature); // TODO: handle generics types + String type = Signature.toString(Signature.getTypeErasure(signature.substring(dims))); + + ClassNode node = ClassHelper.make(type); + while (dims-- > 0) { + node = node.makeArray(); + } + return node; } } diff --git a/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/model/JavaCoreUtil.java b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/model/JavaCoreUtil.java new file mode 100644 index 0000000000..c375d1889e --- /dev/null +++ b/base/org.eclipse.jdt.groovy.core/src/org/codehaus/jdt/groovy/model/JavaCoreUtil.java @@ -0,0 +1,61 @@ +/* + * Copyright 2009-2018 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.codehaus.jdt.groovy.model; + +import org.codehaus.groovy.ast.ConstructorNode; +import org.codehaus.groovy.ast.MethodNode; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IMethod; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.groovy.core.util.GroovyUtils; +import org.eclipse.jdt.internal.core.util.Util; + +/** + * @see org.eclipse.jdt.internal.corext.util.JavaModelUtil + */ +public class JavaCoreUtil { + + private JavaCoreUtil() {} + + public static IMethod findMethod(MethodNode methodNode, IType declaringType) { + try { + char[] methodName = methodNode.getName().toCharArray(); + String[] paramTypes = GroovyUtils.getParameterTypeSignatures(methodNode, declaringType.isBinary()); + return Util.findMethod(declaringType, methodName, paramTypes, methodNode instanceof ConstructorNode); + } catch (JavaModelException e) { + Util.log(e); + return null; + } + } + + public static IMethod findMethod(MethodNode methodNode, IJavaElement referenceContext) { + IType declaringType = findType(methodNode.getDeclaringClass().getName(), referenceContext); + return findMethod(methodNode, declaringType); + } + + public static IType findType(String fullyQualifiedName, IJavaElement referenceContext) { + try { + IJavaProject project = referenceContext.getJavaProject(); + return project.findType(fullyQualifiedName.replace('$', '.'), (IProgressMonitor) null); + } catch (JavaModelException e) { + Util.log(e); + return null; + } + } +} diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java index 6e6bee9575..39be2973e1 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.CancellationException; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -105,7 +106,7 @@ import org.codehaus.groovy.transform.stc.StaticTypesMarker; import org.codehaus.jdt.groovy.internal.compiler.ast.JDTResolver; import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; -import org.codehaus.jdt.groovy.model.GroovyProjectFacade; +import org.codehaus.jdt.groovy.model.JavaCoreUtil; import org.codehaus.jdt.groovy.model.ModuleNodeMapper.ModuleNodeInfo; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IStatus; @@ -167,27 +168,36 @@ private static void log(Throwable t, String form, Object... args) { private ConstructorCallExpression enclosingConstructorCall; /** - * The head of the stack is the current property/attribute/methodcall/binary expression being visited. This stack is used so we - * can keep track of the type of the object expressions in these property expressions + * The head of the stack is the current property/attribute/methodcall/binary + * expression being visited. This stack is used so we can keep track of the + * type of the object expressions in these property expressions. */ private final LinkedList completeExpressionStack = new LinkedList<>(); /** - * Keeps track of the type of the object expression corresponding to each frame of the property expression. + * Tracks the declaring type of the current dependent expression. Dependent + * expressions are dependent on a primary expression to find type information. + * This field is only applicable for {@link PropertyExpression}s and {@link MethodCallExpression}s. */ - private final LinkedList primaryTypeStack = new LinkedList<>(); + private final LinkedList dependentDeclarationStack = new LinkedList<>(); /** - * Keeps track of the declaring type of the current dependent expression. Dependent expressions are dependent on a primary - * expression to find type information. this field is only applicable for {@link PropertyExpression}s and - * {@link MethodCallExpression}s. + * Tracks the type of the type of the property field corresponding to each + * frame of the property expression. */ - private final LinkedList dependentDeclarationStack = new LinkedList<>(); + private final LinkedList dependentTypeStack = new LinkedList<>(); /** - * Keeps track of the type of the type of the property field corresponding to each frame of the property expression. + * Tracks the type of the object expression corresponding to each frame of + * the property expression. */ - private final LinkedList dependentTypeStack = new LinkedList<>(); + private final LinkedList primaryTypeStack = new LinkedList<>(); + + /** + * Tracks the anonymous inner class counts for type members. Required for + * calls to {@code IMember.getType("", occurrenceCount);} + */ + private Map occurrenceCounts = new HashMap<>(); private final AssignmentStorer assignmentStorer = new AssignmentStorer(); @@ -254,6 +264,7 @@ public void visitCompilationUnit(ITypeRequestor requestor) { e.printStackTrace(); } } finally { + occurrenceCounts.clear(); scopes.removeLast(); } if (DEBUG) { @@ -662,19 +673,30 @@ private void visitMethodInternal(MethodNode node, boolean isCtor) { * @param node anonymous inner class for enum constant */ private void visitMethodOverrides(ClassNode node) { - scopes.add(new VariableScope(scopes.getLast(), node, false)); + assert node.isEnum() && node.getEnclosingMethod() == null; ASTNode enclosingDeclaration0 = enclosingDeclarationNode; - IJavaElement enclosingElement0 = enclosingElement; - enclosingDeclarationNode = node; + IJavaElement enclosingElement0 = enclosingElement; // enum + enclosingDeclarationNode = scopes.getLast().getEnclosingFieldDeclaration(); try { + IField enumConstant = ((IType) enclosingElement).getField(((FieldNode) enclosingDeclarationNode).getName()); + assert enumConstant != null && enumConstant.exists(); for (MethodNode method : node.getMethods()) { if (method.getEnd() > 0) { - enclosingElement = findAnonType(node).getMethod(method.getName(), GroovyUtils.getParameterTypeSignatures(method, true)); + // TODO: How does the JDT find a method under an enum constant? + enclosingElement = Stream.of(enumConstant.getChildren()).filter(e -> { + if (e instanceof IMethod && e.getElementName().equals(method.getName())) { + /*return Arrays.equals(((IMethod) e).getParameterTypes(), + GroovyUtils.getParameterTypeSignatures(method, enumConstant.isBinary()));*/ + } + return false; + }).findFirst().orElse(enclosingElement0); + visitMethodInternal(method, false); } } + } catch (JavaModelException e) { + log(e, "Error visiting children of %s", enclosingDeclarationNode); } finally { - scopes.removeLast().bubbleUpdates(); enclosingElement = enclosingElement0; enclosingDeclarationNode = enclosingDeclaration0; } @@ -1024,18 +1046,20 @@ public void visitConstructorCallExpression(ConstructorCallExpression node) { IJavaElement enclosingElement0 = enclosingElement; enclosingDeclarationNode = type; try { + IType anon = findAnonType(type); + for (Statement stmt : type.getObjectInitializerStatements()) { stmt.visit(this); } for (FieldNode field : type.getFields()) { if (field.getEnd() > 0) { - enclosingElement = findAnonType(type).getField(field.getName()); + enclosingElement = anon.getField(field.getName()); visitFieldInternal(field); } } for (MethodNode method : type.getMethods()) { if (method.getEnd() > 0) { - enclosingElement = findAnonType(type).getMethod(method.getName(), GroovyUtils.getParameterTypeSignatures(method, true)); + enclosingElement = JavaCoreUtil.findMethod(method, anon); visitMethodInternal(method, false); } } @@ -1895,9 +1919,20 @@ private boolean handleRequestor(Expression node, ClassNode primaryType, TypeLook // - private IType findAnonType(ClassNode node) { - assert GroovyUtils.isAnonymous(node) : node.getName() + " is not anonymous"; - return new GroovyProjectFacade(enclosingElement).groovyClassToJavaType(node); + private IType findAnonType(ClassNode type) { + int occurrenceCount = occurrenceCounts.computeIfAbsent( + enclosingElement, x -> new AtomicInteger()).incrementAndGet(); + try { + for (IJavaElement child : ((IMember) enclosingElement).getChildren()) { + if (child instanceof IType && ((IType) child).isAnonymous() && + ((IType) child).getOccurrenceCount() == occurrenceCount) { + return (IType) child; + } + } + } catch (JavaModelException e) { + log(e, "Error visiting children of %s", type.getName()); + } + return null; } private ClassNode findClassNode(String name) { @@ -2722,7 +2757,7 @@ private static boolean isEnumInit(MethodCallExpression node) { } private static boolean isEnumInit(StaticMethodCallExpression node) { - return (node.getOwnerType().isEnum() && node.getMethod().equals("$INIT")); + return (node.getOwnerType().isEnum() && node.getMethodAsString().equals("$INIT")); } private static boolean isLazy(FieldNode fieldNode) { diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeReferenceSearchRequestor.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeReferenceSearchRequestor.java index 3cbedea4be..bb67df2c5e 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeReferenceSearchRequestor.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeReferenceSearchRequestor.java @@ -24,10 +24,9 @@ import org.codehaus.groovy.ast.ImportNode; import org.codehaus.groovy.ast.expr.ClassExpression; import org.codehaus.jdt.groovy.model.GroovyClassFileWorkingCopy; +import org.codehaus.jdt.groovy.model.JavaCoreUtil; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.jdt.core.search.SearchParticipant; @@ -182,14 +181,9 @@ protected TypeReferenceMatch createMatch(TypeLookupResult result, IJavaElement e IJavaElement element = enclosingElement; if (findDeclaration) { // don't use the enclosing element, but rather use the declaration of the type - try { - ClassNode type = GroovyUtils.getBaseType(result.type); - IJavaElement e = enclosingElement.getJavaProject().findType(type.getName().replace('$', '.'), new NullProgressMonitor()); - if (e != null) { - element = e; - } - } catch (JavaModelException e) { - Util.log(e); + IJavaElement type = JavaCoreUtil.findType(GroovyUtils.getBaseType(result.type).getName(), enclosingElement); + if (type != null) { + element = type; } } return new TypeReferenceMatch(element, getAccuracy(result.confidence), start, end - start, false, participant, element.getResource()); diff --git a/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy b/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy index d7427c3788..252784fb64 100644 --- a/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy +++ b/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/GroovyEclipseTestSuite.groovy @@ -204,7 +204,7 @@ abstract class GroovyEclipseTestSuite { } protected final GroovySnippetCompiler getGroovySnippetCompiler() { - new GroovySnippetCompiler(testProject.groovyProjectFacade) + new GroovySnippetCompiler(testProject.javaProject) } protected final IPackageFragmentRoot getPackageFragmentRoot() { diff --git a/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/TestProject.java b/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/TestProject.java index 82281fe7c6..3b006beec7 100644 --- a/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/TestProject.java +++ b/ide-test/org.codehaus.groovy.eclipse.tests/src/org/codehaus/groovy/eclipse/test/TestProject.java @@ -25,7 +25,6 @@ import org.codehaus.groovy.eclipse.core.builder.GroovyClasspathContainer; import org.codehaus.groovy.runtime.IOGroovyMethods; import org.codehaus.jdt.groovy.model.GroovyNature; -import org.codehaus.jdt.groovy.model.GroovyProjectFacade; import org.eclipse.core.internal.events.BuildCommand; import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IContainer; @@ -101,10 +100,6 @@ public IPackageFragmentRoot getSourceFolder() { return sourceFolder; } - public GroovyProjectFacade getGroovyProjectFacade() { - return new GroovyProjectFacade(javaProject); - } - public boolean hasGroovyContainer() throws Exception { for (IClasspathEntry entry : javaProject.getRawClasspath()) { if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER && diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyExtendedCompletionContext.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyExtendedCompletionContext.java index 874142e8a1..336d69e2e3 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyExtendedCompletionContext.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/completions/GroovyExtendedCompletionContext.java @@ -24,7 +24,7 @@ import org.codehaus.groovy.eclipse.codeassist.GroovyContentAssist; import org.codehaus.groovy.eclipse.codeassist.ProposalUtils; import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext; -import org.codehaus.jdt.groovy.model.GroovyProjectFacade; +import org.codehaus.jdt.groovy.model.JavaCoreUtil; import org.codehaus.jdt.groovy.model.ModuleNodeMapper.ModuleNodeInfo; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; @@ -134,7 +134,7 @@ private IJavaElement[] computeVisibleElements(String typeSignature) { // add enum constants if target type is an enum if (targetType.isEnum()) { try { - IType enumType = new GroovyProjectFacade(enclosingElement).groovyClassToJavaType(targetType); + IType enumType = JavaCoreUtil.findType(targetType.getName(), enclosingElement); for (IField enumField : enumType.getFields()) { if (enumField.isEnumConstant()) { visibleElements.putIfAbsent(enumField.getElementName(), enumField); diff --git a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java index bde2e75283..1fd5569c7b 100644 --- a/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java +++ b/ide/org.codehaus.groovy.eclipse.codeassist.completion/src/org/codehaus/groovy/eclipse/codeassist/proposals/GroovyMethodProposal.java @@ -29,7 +29,7 @@ import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext; import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistLocation; import org.codehaus.groovy.eclipse.codeassist.requestor.MethodInfoContentAssistContext; -import org.eclipse.core.runtime.NullProgressMonitor; +import org.codehaus.jdt.groovy.model.JavaCoreUtil; import org.eclipse.jdt.core.CompletionFlags; import org.eclipse.jdt.core.CompletionProposal; import org.eclipse.jdt.core.ICompilationUnit; @@ -357,7 +357,7 @@ private char[][] getSpecialParameterNames(Parameter[] params) { private IType findDeclaringType(ICompilationUnit unit, MethodNode method) throws JavaModelException { if (cachedDeclaringType == null) { - cachedDeclaringType = unit.getJavaProject().findType(method.getDeclaringClass().getName(), new NullProgressMonitor()); + cachedDeclaringType = JavaCoreUtil.findType(method.getDeclaringClass().getName(), unit); } return cachedDeclaringType; } diff --git a/ide/org.codehaus.groovy.eclipse.codebrowsing/src/org/codehaus/groovy/eclipse/codebrowsing/requestor/CodeSelectRequestor.java b/ide/org.codehaus.groovy.eclipse.codebrowsing/src/org/codehaus/groovy/eclipse/codebrowsing/requestor/CodeSelectRequestor.java index 2b0bf15850..8ec2660cb9 100644 --- a/ide/org.codehaus.groovy.eclipse.codebrowsing/src/org/codehaus/groovy/eclipse/codebrowsing/requestor/CodeSelectRequestor.java +++ b/ide/org.codehaus.groovy.eclipse.codebrowsing/src/org/codehaus/groovy/eclipse/codebrowsing/requestor/CodeSelectRequestor.java @@ -50,6 +50,7 @@ import org.codehaus.jdt.groovy.internal.compiler.ast.JDTMethodNode; import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; import org.codehaus.jdt.groovy.model.GroovyProjectFacade; +import org.codehaus.jdt.groovy.model.JavaCoreUtil; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMethod; @@ -86,7 +87,6 @@ public class CodeSelectRequestor implements ITypeRequestor { private final Region nodeRegion; private final Region selectRegion; private final GroovyCompilationUnit gunit; - private final GroovyProjectFacade project; private ASTNode requestedNode; private IJavaElement requestedElement; @@ -101,7 +101,6 @@ public CodeSelectRequestor(ASTNode node, Region nodeRegion, Region selectRegion, this.selectRegion = selectRegion; gunit = unit; - project = new GroovyProjectFacade(unit); } public ASTNode getRequestedNode() { @@ -235,7 +234,14 @@ private void handleMatch(TypeLookupResult result, IJavaElement enclosingElement) ClassNode declaringType = findDeclaringType(result); if (declaringType != null) { // find it in the java model - IType type = project.groovyClassToJavaType(declaringType); + IType type = (IType) enclosingElement.getAncestor(IJavaElement.TYPE); + if (type == null || !type.getFullyQualifiedName().equals(declaringType.getName())) { + if (!GroovyUtils.isAnonymous(declaringType)) { + type = JavaCoreUtil.findType(declaringType.getName(), enclosingElement); + } else { + type = new GroovyProjectFacade(enclosingElement).groovyClassToJavaType(declaringType); + } + } if (type == null && !gunit.isOnBuildPath()) { // try to find it in the current compilation unit type = gunit.getType(declaringType.getNameWithoutPackage()); @@ -243,6 +249,7 @@ private void handleMatch(TypeLookupResult result, IJavaElement enclosingElement) type = null; } } + if (type != null) { if (qualifier == null) { // find the requested java element diff --git a/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/compiler/GroovySnippetCompiler.java b/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/compiler/GroovySnippetCompiler.java index ec6f303976..f11616e5c5 100644 --- a/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/compiler/GroovySnippetCompiler.java +++ b/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/compiler/GroovySnippetCompiler.java @@ -25,7 +25,6 @@ import org.codehaus.groovy.ast.ModuleNode; import org.codehaus.groovy.eclipse.core.GroovyCore; import org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration; -import org.codehaus.jdt.groovy.model.GroovyProjectFacade; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.WorkingCopyOwner; @@ -49,11 +48,11 @@ public class GroovySnippetCompiler { private INameEnvironment nameEnvironment; - public GroovySnippetCompiler(GroovyProjectFacade project) { + public GroovySnippetCompiler(JavaProject project) { try { - nameEnvironment = new SearchableEnvironment((JavaProject) project.getProject(), (WorkingCopyOwner) null, false); + nameEnvironment = new SearchableEnvironment(project, (WorkingCopyOwner) null, false); } catch (JavaModelException e) { - GroovyCore.logException("Problem initializing snippet compiler for project " + project.getProject().getElementName(), e); + GroovyCore.logException("Problem initializing snippet compiler for project " + project.getElementName(), e); } } diff --git a/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/model/GroovyProjectFacade.java b/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/model/GroovyProjectFacade.java deleted file mode 100644 index d52e74fd5a..0000000000 --- a/ide/org.codehaus.groovy.eclipse.core/src/org/codehaus/groovy/eclipse/core/model/GroovyProjectFacade.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2009-2017 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.eclipse.core.model; - -import org.codehaus.groovy.eclipse.core.GroovyCore; -import org.codehaus.jdt.groovy.model.GroovyNature; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaProject; - -/** - * Provides some useful methods for accessing Groovy state. - */ -@Deprecated -public class GroovyProjectFacade extends org.codehaus.jdt.groovy.model.GroovyProjectFacade { - - @Deprecated // use GroovyNature.hasGroovyNature(IProject) - public static boolean isGroovyProject(IProject proj) { - try { - return proj.hasNature(GroovyNature.GROOVY_NATURE); - } catch (CoreException e) { - GroovyCore.logException("Error getting project nature: " + proj.getName(), e); - return false; - } - } - - public GroovyProjectFacade(IJavaElement element) { - super(element); - } - - public GroovyProjectFacade(IJavaProject project) { - super(project); - } -} diff --git a/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/launchers/GroovyScriptLauncherTab.java b/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/launchers/GroovyScriptLauncherTab.java index b262794f86..47793c85ad 100644 --- a/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/launchers/GroovyScriptLauncherTab.java +++ b/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/launchers/GroovyScriptLauncherTab.java @@ -16,11 +16,18 @@ package org.codehaus.groovy.eclipse.launchers; +import static org.codehaus.jdt.groovy.model.GroovyProjectFacade.isGroovyScript; + +import java.util.ArrayList; import java.util.List; -import org.codehaus.jdt.groovy.model.GroovyProjectFacade; +import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; @@ -28,6 +35,26 @@ public class GroovyScriptLauncherTab extends AbstractGroovyLauncherTab implement @Override protected List findAllRunnableTypes(IJavaProject javaProject) throws JavaModelException { - return new GroovyProjectFacade(javaProject).findAllScripts(); + List results = new ArrayList<>(); + + for (IPackageFragmentRoot root : javaProject.getAllPackageFragmentRoots()) { + if (!root.isReadOnly()) { + for (IJavaElement child : root.getChildren()) { + if (child.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { + for (ICompilationUnit unit : ((IPackageFragment) child).getCompilationUnits()) { + if (unit instanceof GroovyCompilationUnit) { + for (IType type : unit.getTypes()) { + if (isGroovyScript(type)) { + results.add(type); + } + } + } + } + } + } + } + } + + return results; } } diff --git a/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/refactoring/actions/OrganizeGroovyImports.java b/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/refactoring/actions/OrganizeGroovyImports.java index f046f4ebbc..764ce1ef57 100644 --- a/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/refactoring/actions/OrganizeGroovyImports.java +++ b/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/refactoring/actions/OrganizeGroovyImports.java @@ -55,6 +55,7 @@ import org.codehaus.groovy.eclipse.refactoring.actions.TypeSearch.UnresolvedTypeData; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; +import org.codehaus.jdt.groovy.model.JavaCoreUtil; import org.codehaus.jdt.groovy.model.ModuleNodeMapper.ModuleNodeInfo; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; @@ -286,7 +287,7 @@ private void pruneMissingTypes(Iterable imports) throws JavaModelExc } } for (String imp : starImports) { - IType type = unit.getJavaProject().findType(imp + typeName, (IProgressMonitor) null); + IType type = JavaCoreUtil.findType(imp + typeName, unit); if (type != null) { it.remove(); continue on; diff --git a/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/ui/GroovyResourcePropertyTester.java b/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/ui/GroovyResourcePropertyTester.java index 92edea45ec..ce8217bd45 100644 --- a/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/ui/GroovyResourcePropertyTester.java +++ b/ide/org.codehaus.groovy.eclipse.ui/src/org/codehaus/groovy/eclipse/ui/GroovyResourcePropertyTester.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2017 the original author or authors. + * Copyright 2009-2018 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. @@ -15,8 +15,6 @@ */ package org.codehaus.groovy.eclipse.ui; -import java.util.List; - import org.codehaus.groovy.eclipse.core.GroovyCore; import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; import org.codehaus.jdt.groovy.model.GroovyProjectFacade; @@ -77,11 +75,13 @@ public boolean test(Object receiver, String property, Object[] args, Object expe } private boolean isRunnable(ICompilationUnit unit) throws JavaModelException { - boolean result = false; if (unit instanceof GroovyCompilationUnit) { - List runnables = GroovyProjectFacade.findAllRunnableTypes(unit); - result = (!runnables.isEmpty()); + for (IType type : unit.getAllTypes()) { + if (GroovyProjectFacade.hasRunnableMain(type)) { + return true; + } + } } - return result; + return false; } }