Search in sources :

Example 1 with TypeElement

use of org.revapi.java.model.TypeElement in project revapi by revapi.

the class JavaApiAnalyzer method getCorrespondenceDeducer.

@Override
@Nonnull
public CorrespondenceComparatorDeducer getCorrespondenceDeducer() {
    return (l1, l2) -> {
        if (l1.isEmpty() || l2.isEmpty()) {
            return Comparator.naturalOrder();
        }
        // quickly peek inside to see if there even can be methods in the lists - all of the elements in either list
        // will have a common parent and parents of both lists will have the same type or be both null.
        Element parent = l1.get(0).getParent();
        if (!(parent instanceof TypeElement)) {
            return Comparator.naturalOrder();
        }
        IdentityHashMap<MethodElement, Integer> c1MethodOrder = new IdentityHashMap<>(l1.size());
        IdentityHashMap<MethodElement, Integer> c2MethodOrder = new IdentityHashMap<>(l2.size());
        // this will reorder the methods in the lists and will also fill in the method order indices in the maps
        // so that they can be used for comparisons below
        determineOrder(l1, l2, c1MethodOrder, c2MethodOrder);
        // and return a comparator
        return (e1, e2) -> {
            int ret = JavaElementFactory.compareByType(e1, e2);
            if (ret != 0) {
                return ret;
            }
            // let's just look that up.
            if (e1 instanceof MethodElement && e2 instanceof MethodElement) {
                MethodElement m1 = (MethodElement) e1;
                MethodElement m2 = (MethodElement) e2;
                return c1MethodOrder.get(m1) - c2MethodOrder.get(m2);
            } else {
                return e1.compareTo(e2);
            }
        };
    };
}
Also used : DifferenceAnalyzer(org.revapi.DifferenceAnalyzer) CompilationValve(org.revapi.java.compilation.CompilationValve) BiFunction(java.util.function.BiFunction) Element(org.revapi.Element) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) CoIterator(org.revapi.CoIterator) Charset(java.nio.charset.Charset) Util(org.revapi.java.spi.Util) Map(java.util.Map) ArchiveAnalyzer(org.revapi.ArchiveAnalyzer) ThreadFactory(java.util.concurrent.ThreadFactory) ApiAnalyzer(org.revapi.ApiAnalyzer) Nonnull(javax.annotation.Nonnull) InclusionFilter(org.revapi.java.compilation.InclusionFilter) ExecutorService(java.util.concurrent.ExecutorService) Nullable(javax.annotation.Nullable) API(org.revapi.API) CorrespondenceComparatorDeducer(org.revapi.CorrespondenceComparatorDeducer) ProbingEnvironment(org.revapi.java.compilation.ProbingEnvironment) IdentityHashMap(java.util.IdentityHashMap) Iterator(java.util.Iterator) AnalysisContext(org.revapi.AnalysisContext) Collection(java.util.Collection) TypeElement(org.revapi.java.model.TypeElement) Set(java.util.Set) IOException(java.io.IOException) ServiceLoader(java.util.ServiceLoader) Reader(java.io.Reader) Types(javax.lang.model.util.Types) InputStreamReader(java.io.InputStreamReader) Executors(java.util.concurrent.Executors) JavaElementFactory(org.revapi.java.model.JavaElementFactory) Collectors.toList(java.util.stream.Collectors.toList) List(java.util.List) StringReader(java.io.StringReader) TreeMap(java.util.TreeMap) MethodElement(org.revapi.java.model.MethodElement) Check(org.revapi.java.spi.Check) ModelNode(org.jboss.dmr.ModelNode) Pattern(java.util.regex.Pattern) Comparator(java.util.Comparator) TypeElement(org.revapi.java.model.TypeElement) Element(org.revapi.Element) TypeElement(org.revapi.java.model.TypeElement) MethodElement(org.revapi.java.model.MethodElement) IdentityHashMap(java.util.IdentityHashMap) MethodElement(org.revapi.java.model.MethodElement) Nonnull(javax.annotation.Nonnull)

Example 2 with TypeElement

use of org.revapi.java.model.TypeElement in project revapi by revapi.

the class JavaElementDifferenceAnalyzer method appendUseType.

private boolean appendUseType(ProbingEnvironment env, JavaTypeElement ut, List<TypeAndUseSite> path, JavaTypeElement usedType, DeclaredType type, UseSite currentUse, Set<javax.lang.model.element.TypeElement> visitedTypes) {
    javax.lang.model.element.TypeElement useType = ut.getDeclaringElement();
    if (visitedTypes.contains(useType)) {
        return false;
    }
    visitedTypes.add(useType);
    if (ut.isInAPI() && !ut.isInApiThroughUse() && !ut.equals(usedType)) {
        // the class is in the primary API
        path.add(0, new TypeAndUseSite(type, currentUse));
        return true;
    } else {
        Boolean ret = ut.visitUseSites(new UseSite.Visitor<Boolean, Void>() {

            @Nullable
            @Override
            public Boolean visit(@Nonnull DeclaredType visitedType, @Nonnull UseSite use, @Nullable Void parameter) {
                if (traverseToApi(env, usedType, visitedType, use, path, visitedTypes)) {
                    path.add(0, new TypeAndUseSite(type, currentUse));
                    return true;
                }
                return null;
            }

            @Nullable
            @Override
            public Boolean end(DeclaredType type, @Nullable Void parameter) {
                return null;
            }
        }, null);
        if (ret == null) {
            Set<javax.lang.model.element.TypeElement> derivedUseTypes = env.getDerivedTypes(useType);
            for (javax.lang.model.element.TypeElement dut : derivedUseTypes) {
                TypeElement model = env.getTypeMap().get(dut);
                if (model == null) {
                    continue;
                }
                JavaModelElement derivedUseElement = findSameDeclarationUnder(currentUse.getSite(), model);
                if (derivedUseElement == null) {
                    continue;
                }
                UseSite derivedUse = new UseSite(currentUse.getUseType(), derivedUseElement);
                if (appendUseType(env, model, path, usedType, type, derivedUse, visitedTypes)) {
                    ret = true;
                    break;
                }
            }
        }
        return ret == null ? false : ret;
    }
}
Also used : JavaModelElement(org.revapi.java.spi.JavaModelElement) JavaTypeElement(org.revapi.java.spi.JavaTypeElement) TypeElement(org.revapi.java.model.TypeElement) UseSite(org.revapi.java.spi.UseSite) Nullable(javax.annotation.Nullable) DeclaredType(javax.lang.model.type.DeclaredType)

Example 3 with TypeElement

use of org.revapi.java.model.TypeElement in project revapi by revapi.

the class JavaArchiveAnalyzerTest method testTypeParametersDragIntoAPI.

@Test
public void testTypeParametersDragIntoAPI() throws Exception {
    ArchiveAndCompilationPath compRes = createCompiledJar("a.jar", "misc/Generics.java", "misc/GenericsParams.java");
    JavaArchive api = ShrinkWrap.create(JavaArchive.class, "api.jar").addAsResource(compRes.compilationPath.resolve("Generics.class").toFile(), "Generics.class");
    JavaArchive sup = ShrinkWrap.create(JavaArchive.class, "sup.jar").addAsResource(compRes.compilationPath.resolve("GenericsParams.class").toFile(), "GenericsParams.class").addAsResource(compRes.compilationPath.resolve("GenericsParams$TypeParam.class").toFile(), "GenericsParams$TypeParam.class").addAsResource(compRes.compilationPath.resolve("GenericsParams$ExtendsBound.class").toFile(), "GenericsParams$ExtendsBound.class").addAsResource(compRes.compilationPath.resolve("GenericsParams$SuperBound.class").toFile(), "GenericsParams$SuperBound.class").addAsResource(compRes.compilationPath.resolve("GenericsParams$TypeVar.class").toFile(), "GenericsParams$TypeVar.class").addAsResource(compRes.compilationPath.resolve("GenericsParams$TypeVarIface.class").toFile(), "GenericsParams$TypeVarIface.class").addAsResource(compRes.compilationPath.resolve("GenericsParams$TypeVarImpl.class").toFile(), "GenericsParams$TypeVarImpl.class").addAsResource(compRes.compilationPath.resolve("GenericsParams$Unused.class").toFile(), "GenericsParams$Unused.class");
    JavaArchiveAnalyzer analyzer = new JavaArchiveAnalyzer(new API(Arrays.asList(new ShrinkwrapArchive(api)), Arrays.asList(new ShrinkwrapArchive(sup))), Executors.newSingleThreadExecutor(), null, false, InclusionFilter.acceptAll());
    try {
        JavaElementForest forest = analyzer.analyze();
        Set<TypeElement> roots = forest.getRoots();
        Assert.assertEquals(7, roots.size());
        Assert.assertTrue(roots.stream().anyMatch(hasName("class Generics<T extends GenericsParams.TypeVar, GenericsParams.TypeVarIface, U extends Generics<GenericsParams.TypeVarImpl, ?>>")));
        Assert.assertTrue(roots.stream().anyMatch(hasName("class GenericsParams.ExtendsBound")));
        Assert.assertTrue(roots.stream().anyMatch(hasName("class GenericsParams.SuperBound")));
        Assert.assertTrue(roots.stream().anyMatch(hasName("class GenericsParams.TypeParam")));
        Assert.assertTrue(roots.stream().anyMatch(hasName("class GenericsParams.TypeVar")));
        Assert.assertTrue(roots.stream().anyMatch(hasName("interface GenericsParams.TypeVarIface")));
        Assert.assertTrue(roots.stream().anyMatch(hasName("class GenericsParams.TypeVarImpl")));
        Assert.assertFalse(roots.stream().anyMatch(hasName("class GenericsParams.Unused")));
    } finally {
        deleteDir(compRes.compilationPath);
        analyzer.getCompilationValve().removeCompiledResults();
    }
}
Also used : JavaElementForest(org.revapi.java.model.JavaElementForest) TypeElement(org.revapi.java.model.TypeElement) API(org.revapi.API) JavaArchive(org.jboss.shrinkwrap.api.spec.JavaArchive) Test(org.junit.Test)

Example 4 with TypeElement

use of org.revapi.java.model.TypeElement in project revapi by revapi.

the class JavaElementDifferenceAnalyzer method beginAnalysis.

@Override
public void beginAnalysis(@Nullable Element oldElement, @Nullable Element newElement) {
    Timing.LOG.trace("Beginning analysis of {} and {}.", oldElement, newElement);
    Check.Type elementsType = getCheckType(oldElement, newElement);
    Collection<Check> possibleChecks = nonExistenceMode ? descendingChecksByTypes.getOrDefault(elementsType, emptySet()) : checksByInterest.get(elementsType);
    if (conforms(oldElement, newElement, TypeElement.class)) {
        checkTypeStack.push(CheckType.CLASS);
        checksStack.push(possibleChecks);
        lastAnnotationResults = null;
        for (Check c : possibleChecks) {
            Stats.of(c.getClass().getName()).start();
            c.visitClass(oldElement == null ? null : (TypeElement) oldElement, newElement == null ? null : (TypeElement) newElement);
            Stats.of(c.getClass().getName()).end(oldElement, newElement);
        }
    } else if (conforms(oldElement, newElement, AnnotationElement.class)) {
        // treat them a bit differently
        if (lastAnnotationResults == null) {
            lastAnnotationResults = new ArrayList<>(4);
        }
        // Annotations are handled differently and this would lead to the stack corruption and missed problems!!!
        for (Check c : possibleChecks) {
            Stats.of(c.getClass().getName()).start();
            List<Difference> cps = c.visitAnnotation(oldElement == null ? null : (AnnotationElement) oldElement, newElement == null ? null : (AnnotationElement) newElement);
            if (cps != null) {
                lastAnnotationResults.addAll(cps);
            }
            Stats.of(c.getClass().getName()).end(oldElement, newElement);
        }
    } else if (conforms(oldElement, newElement, FieldElement.class)) {
        doRestrictedCheck((FieldElement) oldElement, (FieldElement) newElement, CheckType.FIELD, possibleChecks);
    } else if (conforms(oldElement, newElement, MethodElement.class)) {
        doRestrictedCheck((MethodElement) oldElement, (MethodElement) newElement, CheckType.METHOD, possibleChecks);
    } else if (conforms(oldElement, newElement, MethodParameterElement.class)) {
        doRestrictedCheck((MethodParameterElement) oldElement, (MethodParameterElement) newElement, CheckType.METHOD_PARAMETER, possibleChecks);
    }
    if (!nonExistenceMode && (oldElement == null || newElement == null)) {
        nonExistenceMode = true;
        nonExistenceOldRoot = oldElement;
        nonExistenceNewRoot = newElement;
    }
}
Also used : AnnotationElement(org.revapi.java.model.AnnotationElement) JavaTypeElement(org.revapi.java.spi.JavaTypeElement) TypeElement(org.revapi.java.model.TypeElement) Check(org.revapi.java.spi.Check) ArrayList(java.util.ArrayList) MethodElement(org.revapi.java.model.MethodElement) ArrayList(java.util.ArrayList) Collections.emptyList(java.util.Collections.emptyList) List(java.util.List)

Example 5 with TypeElement

use of org.revapi.java.model.TypeElement in project revapi by revapi.

the class JavaArchiveAnalyzerTest method testWithSupplementary.

@Test
public void testWithSupplementary() throws Exception {
    ArchiveAndCompilationPath compRes = createCompiledJar("a.jar", "v1/supplementary/a/A.java", "v1/supplementary/b/B.java", "v1/supplementary/a/C.java");
    JavaArchive api = ShrinkWrap.create(JavaArchive.class, "api.jar").addAsResource(compRes.compilationPath.resolve("A.class").toFile(), "A.class");
    JavaArchive sup = ShrinkWrap.create(JavaArchive.class, "sup.jar").addAsResource(compRes.compilationPath.resolve("B.class").toFile(), "B.class").addAsResource(compRes.compilationPath.resolve("B$T$1.class").toFile(), "B$T$1.class").addAsResource(compRes.compilationPath.resolve("B$T$1$TT$1.class").toFile(), "B$T$1$TT$1.class").addAsResource(compRes.compilationPath.resolve("B$T$2.class").toFile(), "B$T$2.class").addAsResource(compRes.compilationPath.resolve("C.class").toFile(), "C.class").addAsResource(compRes.compilationPath.resolve("B$UsedByIgnoredClass.class").toFile(), "B$UsedByIgnoredClass.class").addAsResource(compRes.compilationPath.resolve("A$PrivateEnum.class").toFile(), "A$PrivateEnum.class");
    JavaArchiveAnalyzer analyzer = new JavaArchiveAnalyzer(new API(Arrays.asList(new ShrinkwrapArchive(api)), Arrays.asList(new ShrinkwrapArchive(sup))), Executors.newSingleThreadExecutor(), null, false, InclusionFilter.acceptAll());
    try {
        JavaElementForest forest = analyzer.analyze();
        Assert.assertEquals(3, forest.getRoots().size());
        Iterator<TypeElement> roots = forest.getRoots().iterator();
        TypeElement A = roots.next();
        TypeElement B_T$1 = roots.next();
        TypeElement B_T$2 = roots.next();
        Assert.assertEquals("A", A.getCanonicalName());
        Assert.assertEquals("A", A.getDeclaringElement().getQualifiedName().toString());
        Assert.assertEquals("B.T$1", B_T$1.getCanonicalName());
        Assert.assertEquals("B.T$1", B_T$1.getDeclaringElement().getQualifiedName().toString());
        Assert.assertEquals("B.T$2", B_T$2.getCanonicalName());
        Assert.assertEquals("B.T$2", B_T$2.getDeclaringElement().getQualifiedName().toString());
    } finally {
        deleteDir(compRes.compilationPath);
        analyzer.getCompilationValve().removeCompiledResults();
    }
}
Also used : JavaElementForest(org.revapi.java.model.JavaElementForest) TypeElement(org.revapi.java.model.TypeElement) API(org.revapi.API) JavaArchive(org.jboss.shrinkwrap.api.spec.JavaArchive) Test(org.junit.Test)

Aggregations

TypeElement (org.revapi.java.model.TypeElement)5 API (org.revapi.API)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Nullable (javax.annotation.Nullable)2 JavaArchive (org.jboss.shrinkwrap.api.spec.JavaArchive)2 Test (org.junit.Test)2 IOException (java.io.IOException)1 InputStreamReader (java.io.InputStreamReader)1 Reader (java.io.Reader)1 StringReader (java.io.StringReader)1 Charset (java.nio.charset.Charset)1 Collection (java.util.Collection)1 Collections.emptyList (java.util.Collections.emptyList)1 Comparator (java.util.Comparator)1 HashMap (java.util.HashMap)1 IdentityHashMap (java.util.IdentityHashMap)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 ServiceLoader (java.util.ServiceLoader)1