Skip to content

Commit

Permalink
#Issue #565 - Create IntersectionTypeImpl that implements javax.lang.…
Browse files Browse the repository at this point in the history
…model.type.IntersectionType (#2702)

When a type variable has more than one super interfaces, we should create an intersection type with all the bounds.
  • Loading branch information
kamilkrzywanski authored Aug 20, 2024
1 parent be7e2a9 commit 430761c
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 0 deletions.
3 changes: 3 additions & 0 deletions org.eclipse.jdt.apt.pluggable.tests/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
<java6processor
class="org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.Bug341298Processor">
</java6processor>
<java6processor
class="org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.Issue565Processor">
</java6processor>
</java6processors>
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package targets.issue565;
import java.io.Serializable;

@Annotation565
public class A <I extends Serializable & Comparable<I> & Runnable>{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package targets.issue565;
import java.lang.annotation.Inherited;

@Inherited
public @interface Annotation565 {
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.Bug341298Processor;
import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.Bug468893Processor;
import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.Bug510118Processor;
import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.Issue565Processor;
import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.BugsProc;
import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.InheritedAnnoProc;
import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.TestFinalRoundProc;
Expand Down Expand Up @@ -370,6 +371,19 @@ public void testBug510118() throws Throwable {
assertTrue("Incorrect status received from annotation processor", Bug510118Processor.status());
}

public void testIssue565() throws Throwable {
ProcessorTestStatus.reset();
IJavaProject jproj = createJavaProject(_projectName);
disableJava5Factories(jproj);
IProject proj = jproj.getProject();
IdeTestUtils.copyResources(proj, "targets/issue565", "src/targets/issue565");

AptConfig.setEnabled(jproj, true);
fullBuild();
expectingNoProblems();
assertTrue("Incorrect status received from annotation processor", Issue565Processor.status());
}

public void testBug341298() throws Throwable {
ProcessorTestStatus.reset();
IJavaProject project = createJavaProject(_projectName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*******************************************************************************
* Copyright (c) 2024 Kamil Krzywanski
*
* 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:
* Kamil Krzywanski - initial creation if Interesection type and Implementation
*******************************************************************************/
package org.eclipse.jdt.apt.pluggable.tests.processors.buildertester;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.*;
import javax.lang.model.util.SimpleTypeVisitor8;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@SupportedAnnotationTypes("targets.issue565.Annotation565")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class Issue565Processor extends AbstractProcessor {
private static boolean status = false;

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
// We're not interested in the postprocessing round.
return false;
}

for (Element element : roundEnv.getElementsAnnotatedWith(annotations.stream().findAny().get())) {
if (element instanceof TypeElement) {
keyBuilder.visit(element.asType(), true);
}
}
status = true;
return false;
}

public static boolean status() {
return status;
}

// This is a fragment of querydsl visitor
private final TypeVisitor<List<String>, Boolean> keyBuilder = new SimpleTypeVisitor8<>() {
private final List<String> defaultValue = Collections.singletonList("Object");

private List<String> visitBase(TypeMirror t) {
List<String> rv = new ArrayList<>();
String name = t.toString();
if (name.contains("<")) {
name = name.substring(0, name.indexOf('<'));
}
rv.add(name);
return rv;
}

@Override
public List<String> visitDeclared(DeclaredType t, Boolean p) {
List<String> rv = visitBase(t);
for (TypeMirror arg : t.getTypeArguments()) {
if (p) {
rv.addAll(visit(arg, false));
} else {
rv.add(arg.toString());
}
}
return rv;
}

@Override
public List<String> visitTypeVariable(TypeVariable t, Boolean p) {
List<String> rv = visitBase(t);
if (t.getUpperBound() != null) {
rv.addAll(visit(t.getUpperBound(), p));
}
if (t.getLowerBound() != null) {
rv.addAll(visit(t.getLowerBound(), p));
}
return rv;
}

@Override
public List<String> visitIntersection(IntersectionType t, Boolean p) {
return t.getBounds().get(0).accept(this, p);
}

@Override
public List<String> visitNull(NullType t, Boolean p) {
return defaultValue;
}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright (c) 2024 Kamil Krzywanski 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:
* Kamil Krzywanski - initial creation if Interesection type and Implementation
*******************************************************************************/

package org.eclipse.jdt.internal.compiler.apt.model;

import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;

import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import java.util.Arrays;
import java.util.List;

/**
* Implementation of the WildcardType
*/
public class IntersectionTypeImpl extends TypeMirrorImpl implements IntersectionType {
private final List<? extends TypeMirror> bounds;

IntersectionTypeImpl(BaseProcessingEnvImpl env, TypeVariableBinding binding) {
super(env, binding);
this.bounds = Arrays.stream(binding.superInterfaces).map(referenceBinding -> this._env.getFactory().newTypeMirror(referenceBinding)).toList();
}

/* (non-Javadoc)
* @see javax.lang.model.type.TypeMirror#getKind()
*/
@Override
public TypeKind getKind() {
return TypeKind.INTERSECTION;
}
/* (non-Javadoc)
* @see javax.lang.model.type.WildcardType#getSuperBound()
*/
@Override
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitIntersection(this, p);
}

/* (non-Javadoc)
* @see javax.lang.model.type.IntersectionType#getBounds()
*/
@Override
public List<? extends TypeMirror> getBounds() {
return this.bounds;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public TypeMirror getUpperBound() {
// only one bound that is an interface
return this._env.getFactory().newTypeMirror(typeVariableBinding.upperBound());
}
if (superInterfaces.length > 1) {
return new IntersectionTypeImpl(this._env, typeVariableBinding);
}

return this._env.getFactory().newTypeMirror(this._binding);
}

Expand Down

0 comments on commit 430761c

Please sign in to comment.