Skip to content

Commit

Permalink
Provide an API to check if an IType is an implicitly declared class.
Browse files Browse the repository at this point in the history
Signed-off-by: David Thompson <davthomp@redhat.com>
  • Loading branch information
datho7561 authored and rgrunber committed Mar 22, 2024
1 parent 6b0e309 commit 696ceaf
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.stream.Stream;

import org.eclipse.jdt.internal.compiler.CompilationResult;
Expand All @@ -24,23 +23,20 @@
*/
public class ImplicitTypeDeclaration extends TypeDeclaration {

private static String NAME_TEMPLATE = "{0}"; //$NON-NLS-1$

public ImplicitTypeDeclaration(CompilationResult result) {
super(result);
this.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccFinal;

Path p = Paths.get(new String(result.fileName));
String basename = p.getFileName().toString();
String classSuffix;
String className;
if (basename.endsWith(".java")) { //$NON-NLS-1$
classSuffix = basename.substring(0, basename.length() - 5);
className = basename.substring(0, basename.length() - 5);
} else {
classSuffix = basename;
className = basename;
}

String nameString = MessageFormat.format(NAME_TEMPLATE, classSuffix);
this.name = nameString.toCharArray();
this.name = className.toCharArray();
}
@Override
public boolean isImplicitType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public interface ExtraCompilerModifiers { // modifier constant
final int AccSealed = ASTNode.Bit29; // used for class/interface to set sealed
final int AccOverriding = ASTNode.Bit29; // record fact a method overrides another one
final int AccImplementing = ASTNode.Bit30; // record fact a method implements another one (it is concrete and overrides an abstract one)
final int AccUnnamed = ASTNode.Bit30; // used for unnamed classes
final int AccGenericSignature = ASTNode.Bit31; // record fact a type/method/field involves generics in its signature (and need special signature attr)
final int AccOutOfFlowScope = ASTNode.Bit29;
}
4 changes: 2 additions & 2 deletions org.eclipse.jdt.core.tests.model/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jdt.core.tests.model;singleton:=true
Bundle-Version: 3.12.400.qualifier
Bundle-Version: 3.13.0.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.jdt.core.tests,
Expand All @@ -15,7 +15,7 @@ Export-Package: org.eclipse.jdt.core.tests,
org.eclipse.jdt.core.tests.rewrite.modifying
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.36.0,4.0.0)",
org.eclipse.jdt.core;bundle-version="[3.38.0,4.0.0)",
org.junit;bundle-version="3.8.1",
org.eclipse.test.performance;bundle-version="[3.1.0,4.0.0)",
org.eclipse.jdt.core.tests.compiler;bundle-version="[3.4.0,4.0.0)",
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.jdt.core.tests.model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<relativePath>../tests-pom/</relativePath>
</parent>
<artifactId>org.eclipse.jdt.core.tests.model</artifactId>
<version>3.12.400-SNAPSHOT</version>
<version>3.13.0-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2504,9 +2504,9 @@ public void testBug459189_002() throws JavaModelException {
this.workingCopies[0] = getWorkingCopy(
"/Completion/src/X.java",
" Integer bar(Integer x) { return null;}\n"+
"public class X {\n"+
"public class Y {\n"+
" Integer foo(){\n"+
" I <Integer, X> i2 = (x) -> {/* HERE */ret /* type ctrl-space after ret */};\n"+
" I <Integer, Y> i2 = (x) -> {/* HERE */ret /* type ctrl-space after ret */};\n"+
" return 0;\n"+
" }\n"+
"}\n"+
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat Inc. and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.model;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;

import junit.framework.Test;

public class JavaSearchBugs21Tests extends AbstractJavaSearchTests {

public JavaSearchBugs21Tests(String name) {
super(name);
}

public static Test suite() {
return buildModelTestSuite(JavaSearchBugs21Tests.class, BYTECODE_DECLARATION_ORDER);
}

class TestCollector extends JavaSearchResultCollector {
@Override
public void acceptSearchMatch(SearchMatch searchMatch) throws CoreException {
super.acceptSearchMatch(searchMatch);
}
}

@Override
IJavaSearchScope getJavaSearchScope() {
return SearchEngine.createJavaSearchScope(new IJavaProject[] {getJavaProject("JavaSearchBugs")});
}
IJavaSearchScope getJavaSearchScopeBugs(String packageName, boolean addSubpackages) throws JavaModelException {
if (packageName == null) return getJavaSearchScope();
return getJavaSearchPackageScope("JavaSearchBugs", packageName, addSubpackages);
}
@Override
public ICompilationUnit getWorkingCopy(String path, String source) throws JavaModelException {
if (this.wcOwner == null) {
this.wcOwner = new WorkingCopyOwner() {};
}
return getWorkingCopy(path, source, this.wcOwner);
}
@Override
public void setUpSuite() throws Exception {
super.setUpSuite();
JAVA_PROJECT = setUpJavaProject("JavaSearchBugs", "10");
}
@Override
public void tearDownSuite() throws Exception {
deleteProject("JavaSearchBugs");
super.tearDownSuite();
}
@Override
protected void setUp () throws Exception {
super.setUp();
this.resultCollector = new TestCollector();
this.resultCollector.showAccuracy(true);
}

public void testUnnamedClassInModel() throws CoreException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java", """
String foo() {
return "foo";
}
void main() {
System.out.println(foo());
}
""");
IType unnamedType = this.workingCopies[0].getType("X");
assertTrue("Unnamed class should exist in the model", unnamedType.exists());
assertTrue("Unnamed class should be marked as unnamed", unnamedType.isImplicitlyDeclared());
}

public void testNamedClassInModel() throws CoreException {
this.workingCopies = new ICompilationUnit[1];
this.workingCopies[0] = getWorkingCopy("/JavaSearchBugs/src/X.java", """
public class X {
String foo() {
return "foo";
}
void main() {
System.out.println(foo());
}
}
""");
IType namedTyped = this.workingCopies[0].getType("X");
assertTrue("class should exist in the model", namedTyped.exists());
assertTrue("class should be marked as named", !namedTyped.isImplicitlyDeclared());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import java.lang.reflect.*;
import java.util.*;
import java.util.ArrayList;

import org.eclipse.jdt.core.tests.junit.extension.TestCase;

Expand Down Expand Up @@ -71,6 +70,7 @@ public static Test suite() {
allClasses.add(JavaSearchBugs16Tests.class);
allClasses.add(JavaSearchBugs17Tests.class);
allClasses.add(JavaSearchBugs19Tests.class);
allClasses.add(JavaSearchBugs21Tests.class);
allClasses.add(JavaSearchMultipleProjectsTests.class);
allClasses.add(SearchTests.class);
allClasses.add(JavaSearchScopeTests.class);
Expand Down
10 changes: 10 additions & 0 deletions org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,16 @@ IType createType(String contents, IJavaElement sibling, boolean force, IProgress
*/
boolean isSealed() throws JavaModelException;

/**
* Returns whether this type is implicitly declared.
*
* @return true if this type is implicitly declared and false otherwise
* @throws JavaModelException if this element does not exist or if an
* exception occurs while accessing its corresponding resource.
* @since 3.38
*/
boolean isImplicitlyDeclared() throws JavaModelException;

/**
* Returns the record components declared by this record class, or an empty
* array if this is not a record.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.ImplicitTypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
Expand Down Expand Up @@ -719,6 +720,7 @@ protected void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boo
? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated
: currentModifiers & ExtraCompilerModifiers.AccJustFlag;
typeInfo.modifiers |= currentModifiers & (ExtraCompilerModifiers.AccSealed | ExtraCompilerModifiers.AccNonSealed);
typeInfo.modifiers |= typeDeclaration instanceof ImplicitTypeDeclaration ? ExtraCompilerModifiers.AccUnnamed : 0;
typeInfo.name = typeDeclaration.name;
typeInfo.nameSourceStart = isEnumInit ? typeDeclaration.allocation.enumConstant.sourceStart : typeDeclaration.sourceStart;
typeInfo.nameSourceEnd = sourceEnd(typeDeclaration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
Expand Down Expand Up @@ -1160,4 +1161,8 @@ private static boolean isComplianceJava11OrHigher(IJavaProject javaProject) {
public IBinaryType getElementInfo() throws JavaModelException {
return (IBinaryType) super.getElementInfo();
}
@Override
public boolean isImplicitlyDeclared() throws JavaModelException {
return (this.getFlags() & ExtraCompilerModifiers.AccUnnamed) != 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.jdt.internal.codeassist.CompletionEngine;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
import org.eclipse.jdt.internal.core.util.DeduplicationUtil;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
Expand Down Expand Up @@ -1015,4 +1016,8 @@ protected void toStringInfo(int tab, StringBuilder buffer, Object info, boolean
public boolean isLambda() {
return false;
}
@Override
public boolean isImplicitlyDeclared() throws JavaModelException {
return (this.getFlags() & ExtraCompilerModifiers.AccUnnamed) != 0;
}
}

0 comments on commit 696ceaf

Please sign in to comment.