mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
merge AnnotationChangesTracker functionality into DifferentiateStrategy; support Kotlin Deprecation annotations (IJPL-179400)
Merge-request: IJ-MR-156114 Merged-by: Eugene Zhuravlev <eugene.zhuravlev@jetbrains.com> GitOrigin-RevId: ec163f659592bdcde8e73017f77365ff2d0e75f5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5f29a404dc
commit
8a0c4b43a8
-2
@@ -1,2 +0,0 @@
|
||||
# Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
org.jetbrains.jps.dependency.kotlin.NullabilityAnnotationChangesTracker
|
||||
+1
-1
@@ -15,7 +15,7 @@ public final class GeneralJvmDifferentiateStrategy implements DifferentiateStrat
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.dependency.java.GeneralJvmDifferentiateStrategy");
|
||||
|
||||
private static final Iterable<JvmDifferentiateStrategy> ourExtensions = collect(
|
||||
ServiceLoader.load(JvmDifferentiateStrategy.class, GeneralJvmDifferentiateStrategy.class.getClassLoader()),
|
||||
ServiceLoader.load(JvmDifferentiateStrategy.class),
|
||||
new SmartList<>()
|
||||
);
|
||||
|
||||
|
||||
+3
-89
@@ -17,11 +17,6 @@ import static org.jetbrains.jps.javac.Iterators.*;
|
||||
|
||||
public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImpl {
|
||||
|
||||
private static final Iterable<AnnotationChangesTracker> ourAnnotationChangeTrackers = collect(
|
||||
ServiceLoader.load(AnnotationChangesTracker.class, JavaDifferentiateStrategy.class.getClassLoader()),
|
||||
new SmartList<>()
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean isIncremental(DifferentiateContext context, Node<?, ?> affectedNode) {
|
||||
if (affectedNode instanceof JvmClass && ((JvmClass)affectedNode).getFlags().isGenerated()) {
|
||||
@@ -295,32 +290,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
|
||||
}
|
||||
}
|
||||
|
||||
Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff = classDiff.annotations();
|
||||
if (!annotationsDiff.unchanged()) {
|
||||
EnumSet<AnnotationChangesTracker.Recompile> toRecompile = EnumSet.noneOf(AnnotationChangesTracker.Recompile.class);
|
||||
for (AnnotationChangesTracker tracker : ourAnnotationChangeTrackers) {
|
||||
if (toRecompile.containsAll(AnnotationChangesTracker.RECOMPILE_ALL)) {
|
||||
break;
|
||||
}
|
||||
Set<AnnotationChangesTracker.Recompile> result = tracker.classAnnotationsChanged(changedClass, annotationsDiff);
|
||||
if (result.contains(AnnotationChangesTracker.Recompile.USAGES)) {
|
||||
debug("Extension ", tracker.getClass().getName(), " requested class usages recompilation because of changes in annotations list --- adding class usage to affected usages");
|
||||
}
|
||||
if (result.contains(AnnotationChangesTracker.Recompile.SUBCLASSES)) {
|
||||
debug("Extension ", tracker.getClass().getName(), " requested subclasses recompilation because of changes in annotations list --- adding subclasses to affected usages");
|
||||
}
|
||||
toRecompile.addAll(result);
|
||||
}
|
||||
boolean affectUsages = toRecompile.contains(AnnotationChangesTracker.Recompile.USAGES);
|
||||
if (affectUsages) {
|
||||
context.affectUsage(new ClassUsage(changedClass.getReferenceID()));
|
||||
}
|
||||
if (toRecompile.contains(AnnotationChangesTracker.Recompile.SUBCLASSES)) {
|
||||
affectSubclasses(context, future, changedClass.getReferenceID(), affectUsages);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return super.processChangedClass(context, change, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -425,38 +395,6 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff = diff.annotations();
|
||||
Difference.Specifier<ParamAnnotation, ParamAnnotation.Diff> paramAnnotationsDiff = diff.paramAnnotations();
|
||||
if (!annotationsDiff.unchanged() || !paramAnnotationsDiff.unchanged()) {
|
||||
EnumSet<AnnotationChangesTracker.Recompile> toRecompile = EnumSet.noneOf(AnnotationChangesTracker.Recompile.class);
|
||||
for (AnnotationChangesTracker tracker : ourAnnotationChangeTrackers) {
|
||||
if (toRecompile.containsAll(AnnotationChangesTracker.RECOMPILE_ALL)) {
|
||||
break;
|
||||
}
|
||||
Set<AnnotationChangesTracker.Recompile> result = tracker.methodAnnotationsChanged(changedMethod, annotationsDiff, paramAnnotationsDiff);
|
||||
if (result.contains(AnnotationChangesTracker.Recompile.USAGES)) {
|
||||
debug("Extension ", tracker.getClass().getName(), " requested recompilation because of changes in annotations list --- affecting method usages");
|
||||
}
|
||||
if (result.contains(AnnotationChangesTracker.Recompile.SUBCLASSES)) {
|
||||
debug("Extension ", tracker.getClass().getName(), " requested recompilation because of changes in method annotations or method parameter annotations list --- affecting subclasses");
|
||||
}
|
||||
toRecompile.addAll(result);
|
||||
}
|
||||
if (toRecompile.contains(AnnotationChangesTracker.Recompile.USAGES)) {
|
||||
affectMemberUsages(context, changedClass.getReferenceID(), changedMethod, propagated);
|
||||
if (changedMethod.isAbstract() || toRecompile.contains(AnnotationChangesTracker.Recompile.SUBCLASSES)) {
|
||||
for (Pair<JvmClass, JvmMethod> pair : recurse(Pair.create(changedClass, changedMethod), p -> p.second.isOverridable()? future.getOverridingMethods(p.first, p.second, p.second::isSameByJavaRules) : Collections.emptyList(), false)) {
|
||||
JvmNodeReferenceID clsId = pair.first.getReferenceID();
|
||||
JvmMethod meth = pair.getSecond();
|
||||
affectMemberUsages(context, clsId, meth, future.collectSubclassesWithoutMethod(clsId, meth));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toRecompile.contains(AnnotationChangesTracker.Recompile.SUBCLASSES)) {
|
||||
affectSubclasses(context, future, changedClass.getReferenceID(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iterable<Difference.Change<JvmMethod, JvmMethod.Diff>> moreAccessible = collect(filter(methodChanges, ch -> ch.getDiff().accessExpanded()), new SmartList<>());
|
||||
@@ -493,7 +431,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
|
||||
}
|
||||
|
||||
debug("End of changed methods processing");
|
||||
return true;
|
||||
return super.processChangedMethods(context, clsChange, methodChanges, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -843,31 +781,7 @@ public final class JavaDifferentiateStrategy extends JvmDifferentiateStrategyImp
|
||||
}
|
||||
}
|
||||
|
||||
Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff = diff.annotations();
|
||||
if (!annotationsDiff.unchanged()) {
|
||||
EnumSet<AnnotationChangesTracker.Recompile> toRecompile = EnumSet.noneOf(AnnotationChangesTracker.Recompile.class);
|
||||
for (AnnotationChangesTracker tracker : ourAnnotationChangeTrackers) {
|
||||
if (toRecompile.containsAll(AnnotationChangesTracker.RECOMPILE_ALL)) {
|
||||
break;
|
||||
}
|
||||
Set<AnnotationChangesTracker.Recompile> result = tracker.fieldAnnotationsChanged(changedField, annotationsDiff);
|
||||
if (result.contains(AnnotationChangesTracker.Recompile.USAGES)) {
|
||||
debug("Extension ", tracker.getClass().getName(), " requested recompilation because of changes in annotations list --- affecting field usages");
|
||||
}
|
||||
if (result.contains(AnnotationChangesTracker.Recompile.SUBCLASSES)) {
|
||||
debug("Extension ", tracker.getClass().getName(), " requested recompilation because of changes in field annotations list --- affecting subclasses");
|
||||
}
|
||||
toRecompile.addAll(result);
|
||||
}
|
||||
if (toRecompile.contains(AnnotationChangesTracker.Recompile.USAGES)) {
|
||||
affectMemberUsages(context, changedClass.getReferenceID(), changedField, propagated);
|
||||
}
|
||||
if (toRecompile.contains(AnnotationChangesTracker.Recompile.SUBCLASSES)) {
|
||||
affectSubclasses(context, future, changedClass.getReferenceID(), false);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return super.processChangedField(context, clsChange, fieldChange, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,10 +32,7 @@ import java.util.function.Supplier;
|
||||
|
||||
public final class JvmClassNodeBuilder extends ClassVisitor implements NodeBuilder {
|
||||
|
||||
private static final Iterable<AnnotationChangesTracker> ourAnnotationChangeTrackers = Iterators.collect(
|
||||
ServiceLoader.load(AnnotationChangesTracker.class, JvmClassNodeBuilder.class.getClassLoader()),
|
||||
new SmartList<>()
|
||||
);
|
||||
private static final Iterable<JvmDifferentiateStrategy> ourDifferentiateStrategies = Iterators.collect(ServiceLoader.load(JvmDifferentiateStrategy.class), new SmartList<>());
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(JvmClassNodeBuilder.class);
|
||||
public static final String LAMBDA_FACTORY_CLASS = "java/lang/invoke/LambdaMetafactory";
|
||||
@@ -969,8 +966,8 @@ public final class JvmClassNodeBuilder extends ClassVisitor implements NodeBuild
|
||||
}
|
||||
|
||||
private static boolean isAnnotationTracked(TypeRepr.ClassType annotationType) {
|
||||
for (AnnotationChangesTracker tracker : ourAnnotationChangeTrackers) {
|
||||
if (tracker.isAnnotationTracked(annotationType)) {
|
||||
for (JvmDifferentiateStrategy strategy : ourDifferentiateStrategies) {
|
||||
if (strategy.isAnnotationTracked(annotationType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+68
-28
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jps.dependency.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.dependency.DifferentiateContext;
|
||||
import org.jetbrains.jps.dependency.Node;
|
||||
import org.jetbrains.jps.dependency.diff.Difference;
|
||||
@@ -11,6 +12,15 @@ import org.jetbrains.jps.dependency.diff.Difference;
|
||||
*/
|
||||
public interface JvmDifferentiateStrategy {
|
||||
|
||||
/**
|
||||
* @param annotationType the annotation class type to check. DependencyGraph will parse and store only those annotations,
|
||||
* if there exists at least one registered AnnotationTracker that can track annotations of this type
|
||||
* @return true if this AnnotationTracker can track annotations of this type, false otherwise.
|
||||
*/
|
||||
default boolean isAnnotationTracked(@NotNull TypeRepr.ClassType annotationType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isIncremental(DifferentiateContext context, Node<?, ?> affectedNode) {
|
||||
return true;
|
||||
}
|
||||
@@ -46,39 +56,47 @@ public interface JvmDifferentiateStrategy {
|
||||
if (!processChangedClass(context, change, future, present)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JvmClass changedClass = change.getPast();
|
||||
|
||||
Difference.Specifier<JvmMethod, JvmMethod.Diff> methodsDiff = change.getDiff().methods();
|
||||
if (!methodsDiff.unchanged()) {
|
||||
if (!processRemovedMethods(context, change, methodsDiff.removed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processAddedMethods(context, change, methodsDiff.added(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processChangedMethods(context, change, methodsDiff.changed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Difference.Specifier<JvmField, JvmField.Diff> fieldsDiff = change.getDiff().fields();
|
||||
if (!fieldsDiff.unchanged()) {
|
||||
if (!processRemovedFields(context, change, fieldsDiff.removed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processAddedFields(context, change, fieldsDiff.added(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processChangedFields(context, change, fieldsDiff.changed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean processChangedClass(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> change, Utils future, Utils present) {
|
||||
Difference.Specifier<JvmMethod, JvmMethod.Diff> methodsDiff = change.getDiff().methods();
|
||||
if (!methodsDiff.unchanged()) {
|
||||
if (!processRemovedMethods(context, change, methodsDiff.removed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processAddedMethods(context, change, methodsDiff.added(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processChangedMethods(context, change, methodsDiff.changed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Difference.Specifier<JvmField, JvmField.Diff> fieldsDiff = change.getDiff().fields();
|
||||
if (!fieldsDiff.unchanged()) {
|
||||
if (!processRemovedFields(context, change, fieldsDiff.removed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processAddedFields(context, change, fieldsDiff.added(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
if (!processChangedFields(context, change, fieldsDiff.changed(), future, present)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff = change.getDiff().annotations();
|
||||
if (!annotationDiff.unchanged()) {
|
||||
if (!processClassAnnotations(context, change, annotationDiff, future, present)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean processClassAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> change, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff, Utils future, Utils present) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -118,6 +136,18 @@ public interface JvmDifferentiateStrategy {
|
||||
}
|
||||
|
||||
default boolean processChangedMethod(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmMethod, JvmMethod.Diff> methodChange, Utils future, Utils present) {
|
||||
JvmMethod.Diff diff = methodChange.getDiff();
|
||||
Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff = diff.annotations();
|
||||
Difference.Specifier<ParamAnnotation, ParamAnnotation.Diff> paramAnnotationsDiff = diff.paramAnnotations();
|
||||
if (!annotationsDiff.unchanged() || !paramAnnotationsDiff.unchanged()) {
|
||||
if (!processMethodAnnotations(context, clsChange, methodChange, annotationsDiff, paramAnnotationsDiff, future, present)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean processMethodAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmMethod, JvmMethod.Diff> methodChange, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff, Difference.Specifier<ParamAnnotation, ParamAnnotation.Diff> paramAnnotationsDiff, Utils future, Utils present){
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -157,6 +187,16 @@ public interface JvmDifferentiateStrategy {
|
||||
}
|
||||
|
||||
default boolean processChangedField(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmField, JvmField.Diff> fieldChange, Utils future, Utils present) {
|
||||
Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff = fieldChange.getDiff().annotations();
|
||||
if (!annotationDiff.unchanged()) {
|
||||
if (!processFieldAnnotations(context, clsChange, fieldChange, annotationDiff, future, present)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean processFieldAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmField, JvmField.Diff> fieldChange, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff, Utils future, Utils present) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+77
-3
@@ -1,10 +1,14 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jps.dependency.java;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.dependency.*;
|
||||
import org.jetbrains.jps.dependency.diff.Difference;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@@ -12,11 +16,81 @@ import java.util.function.Predicate;
|
||||
import static org.jetbrains.jps.javac.Iterators.*;
|
||||
|
||||
/**
|
||||
* This class provides some common utilities for strategy implementations
|
||||
* This class provides implementation common to all jvm strategies
|
||||
*/
|
||||
public abstract class JvmDifferentiateStrategyImpl implements JvmDifferentiateStrategy {
|
||||
public abstract class JvmDifferentiateStrategyImpl implements JvmDifferentiateStrategy{
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.dependency.java.JvmDifferentiateStrategyImpl");
|
||||
|
||||
protected enum AnnotationAffectionKind {
|
||||
added, removed, changed
|
||||
}
|
||||
protected final <T extends AnnotationInstance, D extends AnnotationInstance.Diff<T>> boolean isAffectedByAnnotations(
|
||||
Proto element, Difference.Specifier<T, D> annotationsDiff, Set<AnnotationAffectionKind> affectionKinds, Predicate<? super TypeRepr.ClassType> annotationSelector
|
||||
) {
|
||||
return !element.isPrivate() && find(getAffectedAnnotations(annotationsDiff, affectionKinds), annotationSelector::test) != null;
|
||||
}
|
||||
|
||||
protected final <T extends AnnotationInstance, D extends AnnotationInstance.Diff<T>> Iterable<TypeRepr.ClassType> getAffectedAnnotations(
|
||||
Difference.Specifier<T, D> annotationsDiff, Set<AnnotationAffectionKind> affectionKinds
|
||||
) {
|
||||
Iterable<? extends T> added = affectionKinds.contains(AnnotationAffectionKind.added)? annotationsDiff.added() : List.of();
|
||||
Iterable<? extends T> removed = affectionKinds.contains(AnnotationAffectionKind.removed)? annotationsDiff.removed() : List.of();
|
||||
Iterable<? extends T> changed = affectionKinds.contains(AnnotationAffectionKind.changed)? map(annotationsDiff.changed(), Difference.Change::getPast) : List.of();
|
||||
return map(flat(List.of(added, removed, changed)), AnnotationInstance::getAnnotationClass);
|
||||
}
|
||||
|
||||
protected enum AnnotationAffectionScope {
|
||||
/**
|
||||
* If present in the returned result set, the usages of the annotated program element (class, field, method) will be affected.
|
||||
* it means that files where this program element is references, will be marked for recompilation
|
||||
*/
|
||||
usages,
|
||||
|
||||
/**
|
||||
* If present in the returned result set, the subclasses of the annotated class will be affected.
|
||||
* If returned for an annotated field/method, the subclasses of the class containing this field/method will be affected.
|
||||
*/
|
||||
subclasses
|
||||
}
|
||||
|
||||
protected void affectClassAnnotationUsages(DifferentiateContext context, Set<AnnotationAffectionScope> toRecompile, Difference.Change<JvmClass, JvmClass.Diff> change, Utils future, Utils present) {
|
||||
JvmClass changedClass = change.getPast();
|
||||
boolean affectUsages = toRecompile.contains(AnnotationAffectionScope.usages);
|
||||
if (affectUsages) {
|
||||
context.affectUsage(new ClassUsage(changedClass.getReferenceID()));
|
||||
}
|
||||
if (toRecompile.contains(AnnotationAffectionScope.subclasses)) {
|
||||
affectSubclasses(context, future, changedClass.getReferenceID(), affectUsages);
|
||||
}
|
||||
}
|
||||
|
||||
protected void affectFieldAnnotationUsages(DifferentiateContext context, Set<AnnotationAffectionScope> toRecompile, Difference.Change<JvmClass, JvmClass.Diff> clsChange, JvmField changedField, Utils future, Utils present) {
|
||||
JvmClass changedClass = clsChange.getPast();
|
||||
if (toRecompile.contains(AnnotationAffectionScope.usages)) {
|
||||
affectMemberUsages(context, changedClass.getReferenceID(), changedField, future.collectSubclassesWithoutField(changedClass.getReferenceID(), changedField));
|
||||
}
|
||||
if (toRecompile.contains(AnnotationAffectionScope.subclasses)) {
|
||||
affectSubclasses(context, future, changedClass.getReferenceID(), false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void affectMethodAnnotationUsages(DifferentiateContext context, Set<AnnotationAffectionScope> toRecompile, Difference.Change<JvmClass, JvmClass.Diff> clsChange, JvmMethod changedMethod, Utils future, Utils present) {
|
||||
JvmClass changedClass = clsChange.getPast();
|
||||
if (toRecompile.contains(AnnotationAffectionScope.usages)) {
|
||||
affectMemberUsages(context, changedClass.getReferenceID(), changedMethod, future.collectSubclassesWithoutMethod(changedClass.getReferenceID(), changedMethod));
|
||||
if (changedMethod.isAbstract() || toRecompile.contains(AnnotationAffectionScope.subclasses)) {
|
||||
for (Pair<JvmClass, JvmMethod> pair : recurse(Pair.create(changedClass, changedMethod), p -> p.second.isOverridable()? future.getOverridingMethods(p.first, p.second, p.second::isSameByJavaRules) : Collections.emptyList(), false)) {
|
||||
JvmNodeReferenceID clsId = pair.first.getReferenceID();
|
||||
JvmMethod meth = pair.getSecond();
|
||||
affectMemberUsages(context, clsId, meth, future.collectSubclassesWithoutMethod(clsId, meth));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toRecompile.contains(AnnotationAffectionScope.subclasses)) {
|
||||
affectSubclasses(context, future, changedClass.getReferenceID(), false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void affectMemberUsages(DifferentiateContext context, JvmNodeReferenceID clsId, ProtoMember member, Iterable<JvmNodeReferenceID> propagated) {
|
||||
affectMemberUsages(context, clsId, member, propagated, null);
|
||||
}
|
||||
|
||||
+97
-4
@@ -23,6 +23,82 @@ import static org.jetbrains.jps.javac.Iterators.*;
|
||||
*/
|
||||
public final class KotlinJvmDifferentiateStrategy extends JvmDifferentiateStrategyImpl {
|
||||
private static final TypeRepr.ClassType JVM_OVERLOADS_ANNOTATION = new TypeRepr.ClassType("kotlin/jvm/JvmOverloads");
|
||||
private static final Set<TypeRepr.ClassType> ourDeprecationAnnotations = Set.of(
|
||||
new TypeRepr.ClassType("kotlin/Deprecated"),
|
||||
new TypeRepr.ClassType("kotlin/DeprecatedSinceKotlin")
|
||||
);
|
||||
private static final Set<String> ourNullabilityAnnotations = Set.of(
|
||||
"org/jetbrains/annotations/Nullable",
|
||||
"androidx/annotation/Nullable",
|
||||
"android/support/annotation/Nullable",
|
||||
"android/annotation/Nullable",
|
||||
"com/android/annotations/Nullable",
|
||||
"org/eclipse/jdt/annotation/Nullable",
|
||||
"org/checkerframework/checker/nullness/qual/Nullable",
|
||||
"javax/annotation/Nullable",
|
||||
"javax/annotation/CheckForNull",
|
||||
"edu/umd/cs/findbugs/annotations/CheckForNull",
|
||||
"edu/umd/cs/findbugs/annotations/Nullable",
|
||||
"edu/umd/cs/findbugs/annotations/PossiblyNull",
|
||||
"io/reactivex/annotations/Nullable",
|
||||
"io/reactivex/rxjava3/annotations/Nullable",
|
||||
|
||||
"javax/annotation/Nonnull",
|
||||
"org/jetbrains/annotations/NotNull",
|
||||
"edu/umd/cs/findbugs/annotations/NonNull",
|
||||
"androidx/annotation/NonNull",
|
||||
"android/support/annotation/NonNull",
|
||||
"android/annotation/NonNull",
|
||||
"com/android/annotations/NonNull",
|
||||
"org/eclipse/jdt/annotation/NonNull",
|
||||
"org/checkerframework/checker/nullness/qual/NonNull",
|
||||
"lombok/NonNull",
|
||||
"io/reactivex/annotations/NonNull",
|
||||
"io/reactivex/rxjava3/annotations/NonNull"
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationTracked(TypeRepr.@NotNull ClassType annotationType) {
|
||||
return ourNullabilityAnnotations.contains(annotationType.getJvmName()) || ourDeprecationAnnotations.contains(annotationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processClassAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> change, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff, Utils future, Utils present) {
|
||||
JvmClass changedClass = change.getPast();
|
||||
if (isAffectedByAnnotations(changedClass, annotationDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.changed), ourDeprecationAnnotations::contains)) {
|
||||
debug("Deprecation annotations changed for ", changedClass.getName(), " --- affecting class usages");
|
||||
affectClassAnnotationUsages(context, EnumSet.of(AnnotationAffectionScope.usages), change, future, present);
|
||||
}
|
||||
return super.processClassAnnotations(context, change, annotationDiff, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processFieldAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmField, JvmField.Diff> fieldChange, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff, Utils future, Utils present) {
|
||||
JvmField changedField = fieldChange.getPast();
|
||||
if (
|
||||
isAffectedByAnnotations(changedField, annotationDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.removed), t -> ourNullabilityAnnotations.contains(t.getJvmName())) ||
|
||||
isAffectedByAnnotations(changedField, annotationDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.changed), ourDeprecationAnnotations::contains)
|
||||
) {
|
||||
debug("Nullability or Deprecation annotations changed for field ", changedField, " --- affecting field usages");
|
||||
affectFieldAnnotationUsages(context, EnumSet.of(AnnotationAffectionScope.usages), clsChange, changedField, future, present);
|
||||
}
|
||||
return super.processFieldAnnotations(context, clsChange, fieldChange, annotationDiff, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processMethodAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmMethod, JvmMethod.Diff> methodChange, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff, Difference.Specifier<ParamAnnotation, ParamAnnotation.Diff> paramAnnotationsDiff, Utils future, Utils present) {
|
||||
JvmMethod changedMethod = methodChange.getPast();
|
||||
if (
|
||||
isAffectedByAnnotations(changedMethod, annotationsDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.removed), t -> ourNullabilityAnnotations.contains(t.getJvmName())) ||
|
||||
isAffectedByAnnotations(changedMethod, paramAnnotationsDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.removed), t -> ourNullabilityAnnotations.contains(t.getJvmName())) ||
|
||||
isAffectedByAnnotations(changedMethod, annotationsDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.changed), ourDeprecationAnnotations::contains)
|
||||
) {
|
||||
debug("Nullability annotations/parameter annotations or Deprecation annotations changed for method ", changedMethod, " --- affecting method usages");
|
||||
EnumSet<AnnotationAffectionScope> affection = changedMethod.isFinal()? EnumSet.of(AnnotationAffectionScope.usages) : EnumSet.of(AnnotationAffectionScope.usages, AnnotationAffectionScope.subclasses);
|
||||
affectMethodAnnotationUsages(context, affection, clsChange, changedMethod, future, present);
|
||||
}
|
||||
return super.processMethodAnnotations(context, clsChange, methodChange, annotationsDiff, paramAnnotationsDiff, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processAddedClasses(DifferentiateContext context, Iterable<JvmClass> addedClasses, Utils future, Utils present) {
|
||||
@@ -351,7 +427,7 @@ public final class KotlinJvmDifferentiateStrategy extends JvmDifferentiateStrate
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
return super.processChangedClass(context, change, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -384,7 +460,7 @@ public final class KotlinJvmDifferentiateStrategy extends JvmDifferentiateStrate
|
||||
debug("Function was inlineable, or has become inlineable or a body of inline method has changed; affecting method usages ", name);
|
||||
affectMemberLookupUsages(context, changedClass, name, future);
|
||||
}
|
||||
return true;
|
||||
return super.processChangedMethod(context, clsChange, methodChange, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -422,7 +498,7 @@ public final class KotlinJvmDifferentiateStrategy extends JvmDifferentiateStrate
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return super.processChangedField(context, clsChange, fieldChange, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -474,6 +550,23 @@ public final class KotlinJvmDifferentiateStrategy extends JvmDifferentiateStrate
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void affectMethodAnnotationUsages(DifferentiateContext context, Set<AnnotationAffectionScope> toRecompile, Difference.Change<JvmClass, JvmClass.Diff> clsChange, JvmMethod changedMethod, Utils future, Utils present) {
|
||||
super.affectMethodAnnotationUsages(context, toRecompile, clsChange, changedMethod, future, present);
|
||||
if (toRecompile.contains(AnnotationAffectionScope.usages)) {
|
||||
JvmClass changedClass = clsChange.getPast();
|
||||
affectMemberLookupUsages(context, changedClass, KJvmUtils.getMethodKotlinName(changedClass, changedMethod), present);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void affectClassAnnotationUsages(DifferentiateContext context, Set<AnnotationAffectionScope> toRecompile, Difference.Change<JvmClass, JvmClass.Diff> change, Utils future, Utils present) {
|
||||
super.affectClassAnnotationUsages(context, toRecompile, change, future, present);
|
||||
if (toRecompile.contains(AnnotationAffectionScope.usages)) {
|
||||
affectClassLookupUsages(context, change.getPast());
|
||||
}
|
||||
}
|
||||
|
||||
private void affectConflictingCallExpressions(DifferentiateContext context, JvmClass cls, JvmMethod clsMethod, Utils utils, @Nullable Predicate<Node<?, ?>> constraint) {
|
||||
if (clsMethod.isPrivate() || clsMethod.isStaticInitializer()) {
|
||||
return;
|
||||
@@ -626,7 +719,7 @@ public final class KotlinJvmDifferentiateStrategy extends JvmDifferentiateStrate
|
||||
private static Iterable<JvmMethod> withJvmOverloads(JvmClass cls, JvmMethod method) {
|
||||
return unique(flat(
|
||||
asIterable(method),
|
||||
filter(cls.getMethods(), m -> Objects.equals(m.getName(), method.getName()) && Objects.equals(m.getType(), method.getType()) && find(m.getAnnotations(), a -> JVM_OVERLOADS_ANNOTATION.equals(a.getAnnotationClass())) != null)
|
||||
filter(cls.getMethods(), m -> Objects.equals(m.getName(), method.getName()) && Objects.equals(m.getType(), method.getType()) && contains(map(m.getAnnotations(), AnnotationInstance::getAnnotationClass), JVM_OVERLOADS_ANNOTATION))
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jps.dependency.kotlin;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.dependency.diff.Difference;
|
||||
import org.jetbrains.jps.dependency.java.*;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jps.javac.Iterators.*;
|
||||
|
||||
public final class NullabilityAnnotationChangesTracker implements AnnotationChangesTracker {
|
||||
private static final Set<String> ourTrackedAnnotations = Set.of(
|
||||
"org/jetbrains/annotations/Nullable",
|
||||
"androidx/annotation/Nullable",
|
||||
"android/support/annotation/Nullable",
|
||||
"android/annotation/Nullable",
|
||||
"com/android/annotations/Nullable",
|
||||
"org/eclipse/jdt/annotation/Nullable",
|
||||
"org/checkerframework/checker/nullness/qual/Nullable",
|
||||
"javax/annotation/Nullable",
|
||||
"javax/annotation/CheckForNull",
|
||||
"edu/umd/cs/findbugs/annotations/CheckForNull",
|
||||
"edu/umd/cs/findbugs/annotations/Nullable",
|
||||
"edu/umd/cs/findbugs/annotations/PossiblyNull",
|
||||
"io/reactivex/annotations/Nullable",
|
||||
"io/reactivex/rxjava3/annotations/Nullable",
|
||||
|
||||
"javax/annotation/Nonnull",
|
||||
"org/jetbrains/annotations/NotNull",
|
||||
"edu/umd/cs/findbugs/annotations/NonNull",
|
||||
"androidx/annotation/NonNull",
|
||||
"android/support/annotation/NonNull",
|
||||
"android/annotation/NonNull",
|
||||
"com/android/annotations/NonNull",
|
||||
"org/eclipse/jdt/annotation/NonNull",
|
||||
"org/checkerframework/checker/nullness/qual/NonNull",
|
||||
"lombok/NonNull",
|
||||
"io/reactivex/annotations/NonNull",
|
||||
"io/reactivex/rxjava3/annotations/NonNull"
|
||||
);
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationTracked(@NotNull TypeRepr.ClassType annotationType) {
|
||||
return ourTrackedAnnotations.contains(annotationType.getJvmName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Recompile> methodAnnotationsChanged(JvmMethod method, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff, Difference.Specifier<ParamAnnotation, ParamAnnotation.Diff> paramAnnotationsDiff) {
|
||||
if (isAffected(map(flat(List.of(annotationsDiff.added(), annotationsDiff.removed(), paramAnnotationsDiff.added(), paramAnnotationsDiff.removed())), AnnotationInstance::getAnnotationClass))) {
|
||||
return method.isFinal()? EnumSet.of(Recompile.USAGES) : EnumSet.of(Recompile.USAGES, Recompile.SUBCLASSES);
|
||||
}
|
||||
return RECOMPILE_NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Recompile> fieldAnnotationsChanged(JvmField field, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff) {
|
||||
return isAffected(map(flat(annotationsDiff.added(), annotationsDiff.removed()), AnnotationInstance::getAnnotationClass))? EnumSet.of(Recompile.USAGES) : RECOMPILE_NONE;
|
||||
}
|
||||
|
||||
private static boolean isAffected(Iterable<TypeRepr.ClassType> addedOrRemoved) {
|
||||
return !isEmpty(filter(addedOrRemoved, t -> ourTrackedAnnotations.contains(t.getJvmName())));
|
||||
}
|
||||
}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
# Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
org.jetbrains.jps.dependency.java.MockAnnotationsChangeTracker
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
# Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
org.jetbrains.jps.dependency.java.TestJvmDifferentiateStrategy
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jps.dependency.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.java.dependencyView.MockAnnotation;
|
||||
import org.jetbrains.jps.builders.java.dependencyView.MockHierarchyAnnotation;
|
||||
import org.jetbrains.jps.dependency.diff.Difference;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jps.javac.Iterators.*;
|
||||
|
||||
public final class MockAnnotationsChangeTracker implements AnnotationChangesTracker {
|
||||
private static final String ANOTATION_NAME = MockAnnotation.class.getName().replace('.', '/');
|
||||
private static final String HIERARCHY_ANOTATION_NAME = MockHierarchyAnnotation.class.getName().replace('.', '/');
|
||||
private static final Set<String> KOTLIN_TESTS_ANOTATION_NAMES = Set.of("foo/Ann", "Ann");
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationTracked(@NotNull TypeRepr.ClassType annotationType) {
|
||||
String typeName = annotationType.getJvmName();
|
||||
return KOTLIN_TESTS_ANOTATION_NAMES.contains(typeName) || Objects.equals(ANOTATION_NAME, typeName) || Objects.equals(HIERARCHY_ANOTATION_NAME, typeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Recompile> methodAnnotationsChanged(JvmMethod method, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff, Difference.Specifier<ParamAnnotation, ParamAnnotation.Diff> paramAnnotationsDiff) {
|
||||
//return RECOMPILE_NONE;
|
||||
return handleChanges(
|
||||
map(flat(List.of(annotationsDiff.added(), annotationsDiff.removed(), map(annotationsDiff.changed(), Difference.Change::getPast), paramAnnotationsDiff.added(), paramAnnotationsDiff.removed(), map(paramAnnotationsDiff.changed(), Difference.Change::getPast))), AnnotationInstance::getAnnotationClass)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Recompile> fieldAnnotationsChanged(JvmField field, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff) {
|
||||
//return RECOMPILE_NONE;
|
||||
return handleChanges(
|
||||
map(flat(List.of(annotationsDiff.added(), annotationsDiff.removed(), map(annotationsDiff.changed(), Difference.Change::getPast))), AnnotationInstance::getAnnotationClass)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Recompile> classAnnotationsChanged(JvmClass aClass, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff) {
|
||||
//return RECOMPILE_NONE;
|
||||
return handleChanges(
|
||||
map(flat(List.of(annotationsDiff.added(), annotationsDiff.removed(), map(annotationsDiff.changed(), Difference.Change::getPast))), AnnotationInstance::getAnnotationClass)
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<Recompile> handleChanges(Iterable<TypeRepr.ClassType> changes) {
|
||||
final Set<Recompile> result = EnumSet.noneOf(Recompile.class);
|
||||
if (containsAnnotation(ANOTATION_NAME, changes)) {
|
||||
result.add(Recompile.USAGES);
|
||||
}
|
||||
if (containsAnnotation(HIERARCHY_ANOTATION_NAME, changes)) {
|
||||
result.add(Recompile.SUBCLASSES);
|
||||
}
|
||||
if (containsAnnotation(KOTLIN_TESTS_ANOTATION_NAMES, changes)) {
|
||||
result.addAll(RECOMPILE_ALL);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean containsAnnotation(@NotNull String annotationName, Iterable<TypeRepr.ClassType> classes) {
|
||||
return containsAnnotation(Set.of(annotationName), classes);
|
||||
}
|
||||
private static boolean containsAnnotation(Set<String> annotationNames, Iterable<TypeRepr.ClassType> classes) {
|
||||
return !isEmpty(filter(classes, type -> annotationNames.contains(type.getJvmName())));
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.jps.dependency.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.java.dependencyView.MockAnnotation;
|
||||
import org.jetbrains.jps.builders.java.dependencyView.MockHierarchyAnnotation;
|
||||
import org.jetbrains.jps.dependency.DifferentiateContext;
|
||||
import org.jetbrains.jps.dependency.diff.Difference;
|
||||
import org.jetbrains.jps.javac.Iterators;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* The main purpose of this class is to register the annotation tracker for mock and test annotations used in tests
|
||||
*/
|
||||
public class TestJvmDifferentiateStrategy extends JvmDifferentiateStrategyImpl {
|
||||
|
||||
private static final String ANOTATION_NAME = MockAnnotation.class.getName().replace('.', '/');
|
||||
private static final String HIERARCHY_ANOTATION_NAME = MockHierarchyAnnotation.class.getName().replace('.', '/');
|
||||
private static final Set<String> KOTLIN_TESTS_ANOTATION_NAMES = Set.of("foo/Ann", "Ann");
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationTracked(@NotNull TypeRepr.ClassType annotationType) {
|
||||
String typeName = annotationType.getJvmName();
|
||||
return KOTLIN_TESTS_ANOTATION_NAMES.contains(typeName) || Objects.equals(ANOTATION_NAME, typeName) || Objects.equals(HIERARCHY_ANOTATION_NAME, typeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processClassAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> change, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff, Utils future, Utils present) {
|
||||
Set<AnnotationAffectionScope> affectionScope = getAffectionScope(getAffectedAnnotations(annotationDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.removed, AnnotationAffectionKind.changed)));
|
||||
if (!affectionScope.isEmpty()) {
|
||||
affectClassAnnotationUsages(context, affectionScope, change, future, present);
|
||||
}
|
||||
return super.processClassAnnotations(context, change, annotationDiff, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processFieldAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmField, JvmField.Diff> fieldChange, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationDiff, Utils future, Utils present) {
|
||||
Set<AnnotationAffectionScope> affectionScope = getAffectionScope(getAffectedAnnotations(annotationDiff, EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.removed, AnnotationAffectionKind.changed)));
|
||||
if (!affectionScope.isEmpty()) {
|
||||
affectFieldAnnotationUsages(context, affectionScope, clsChange, fieldChange.getPast(), future, present);
|
||||
}
|
||||
return super.processFieldAnnotations(context, clsChange, fieldChange, annotationDiff, future, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processMethodAnnotations(DifferentiateContext context, Difference.Change<JvmClass, JvmClass.Diff> clsChange, Difference.Change<JvmMethod, JvmMethod.Diff> methodChange, Difference.Specifier<ElementAnnotation, ElementAnnotation.Diff> annotationsDiff, Difference.Specifier<ParamAnnotation, ParamAnnotation.Diff> paramAnnotationsDiff, Utils future, Utils present) {
|
||||
EnumSet<AnnotationAffectionKind> affectionKinds = EnumSet.of(AnnotationAffectionKind.added, AnnotationAffectionKind.removed, AnnotationAffectionKind.changed);
|
||||
Set<AnnotationAffectionScope> affectionScope = getAffectionScope(
|
||||
Iterators.flat(getAffectedAnnotations(annotationsDiff, affectionKinds), getAffectedAnnotations(paramAnnotationsDiff, affectionKinds))
|
||||
);
|
||||
if (!affectionScope.isEmpty()) {
|
||||
affectMethodAnnotationUsages(context, affectionScope, clsChange, methodChange.getPast(), future, present);
|
||||
}
|
||||
return super.processMethodAnnotations(context, clsChange, methodChange, annotationsDiff, paramAnnotationsDiff, future, present);
|
||||
}
|
||||
|
||||
private static Set<AnnotationAffectionScope> getAffectionScope(Iterable<TypeRepr.ClassType> trackedAnnotations) {
|
||||
Set<AnnotationAffectionScope> result = EnumSet.noneOf(AnnotationAffectionScope.class);
|
||||
for (TypeRepr.ClassType annotation : trackedAnnotations) {
|
||||
if (ANOTATION_NAME.equals(annotation.getJvmName())) {
|
||||
result.add(AnnotationAffectionScope.usages);
|
||||
}
|
||||
else if (HIERARCHY_ANOTATION_NAME.equals(annotation.getJvmName())) {
|
||||
result.add(AnnotationAffectionScope.subclasses);
|
||||
}
|
||||
else if (KOTLIN_TESTS_ANOTATION_NAMES.contains(annotation.getJvmName())) {
|
||||
result.addAll(EnumSet.of(AnnotationAffectionScope.usages, AnnotationAffectionScope.subclasses));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/Util.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/util.kt
|
||||
End of files
|
||||
Exit code: OK
|
||||
------------------------------------------
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/Client.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/client.kt
|
||||
End of files
|
||||
Exit code: ABORT
|
||||
------------------------------------------
|
||||
COMPILATION FAILED
|
||||
'fun foo(param: String): Int' is deprecated. message.
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class Client {
|
||||
fun test(u: Util) {
|
||||
val a = u.foo("param")
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
@Deprecated("message")
|
||||
fun foo(param : String) = 10
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
@Deprecated("message", level = DeprecationLevel.ERROR)
|
||||
fun foo(param : String) = 10
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/Util.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/util.kt
|
||||
End of files
|
||||
Exit code: OK
|
||||
------------------------------------------
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/Client.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/client.kt
|
||||
End of files
|
||||
Exit code: ABORT
|
||||
------------------------------------------
|
||||
COMPILATION FAILED
|
||||
'var foo: Int' is deprecated. message.
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class Client {
|
||||
fun test(u: Util) {
|
||||
val a = u.foo
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
@Deprecated("message")
|
||||
var foo = 10
|
||||
get
|
||||
set
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
@Deprecated("message", level = DeprecationLevel.ERROR)
|
||||
var foo = 10
|
||||
get
|
||||
set
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/Util.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/util.kt
|
||||
End of files
|
||||
Exit code: OK
|
||||
------------------------------------------
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/ClientGet.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/clientGet.kt
|
||||
End of files
|
||||
Exit code: ABORT
|
||||
------------------------------------------
|
||||
COMPILATION FAILED
|
||||
'var foo: Int' is deprecated. message.
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class ClientGet {
|
||||
fun test(u: Util) {
|
||||
val a = u.foo
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class ClientSet {
|
||||
fun test(u: Util) {
|
||||
u.foo = 10
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
var foo = 10
|
||||
@Deprecated("message")
|
||||
get
|
||||
set
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
var foo = 10
|
||||
@Deprecated("message", level = DeprecationLevel.ERROR)
|
||||
get
|
||||
set
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
================ Step #1 =================
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/Util.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/util.kt
|
||||
End of files
|
||||
Exit code: OK
|
||||
------------------------------------------
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/test/ClientSet.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/clientSet.kt
|
||||
End of files
|
||||
Exit code: ABORT
|
||||
------------------------------------------
|
||||
COMPILATION FAILED
|
||||
'var foo: Int' is deprecated. message.
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class ClientGet {
|
||||
fun test(u: Util) {
|
||||
val a = u.foo
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class ClientSet {
|
||||
fun test(u: Util) {
|
||||
u.foo = 10
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
var foo = 10
|
||||
get
|
||||
@Deprecated("message")
|
||||
set
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
class Util {
|
||||
var foo = 10
|
||||
get
|
||||
@Deprecated("message", level = DeprecationLevel.ERROR)
|
||||
set
|
||||
}
|
||||
+20
@@ -105,6 +105,26 @@ public class IncrementalK2JvmJpsTestGenerated extends AbstractIncrementalK2JvmJp
|
||||
runTest("pureKotlin/annotations/");
|
||||
}
|
||||
|
||||
@TestMetadata("deprecateFunction")
|
||||
public void testDeprecateFunction() throws Exception {
|
||||
runTest("pureKotlin/deprecateFunction/");
|
||||
}
|
||||
|
||||
@TestMetadata("deprecateProperty")
|
||||
public void testDeprecateProperty() throws Exception {
|
||||
runTest("pureKotlin/deprecateProperty/");
|
||||
}
|
||||
|
||||
@TestMetadata("deprecatePropertyGetter")
|
||||
public void testDeprecatePropertyGetter() throws Exception {
|
||||
runTest("pureKotlin/deprecatePropertyGetter/");
|
||||
}
|
||||
|
||||
@TestMetadata("deprecatePropertySetter")
|
||||
public void testDeprecatePropertySetter() throws Exception {
|
||||
runTest("pureKotlin/deprecatePropertySetter/");
|
||||
}
|
||||
|
||||
@TestMetadata("anonymousObjectChanged")
|
||||
public void testAnonymousObjectChanged() throws Exception {
|
||||
runTest("pureKotlin/anonymousObjectChanged/");
|
||||
|
||||
Reference in New Issue
Block a user