Skip to content

Commit

Permalink
Remove extra rounds
Browse files Browse the repository at this point in the history
  • Loading branch information
Rawi01 committed Sep 21, 2023
1 parent a6e3138 commit 0751ddc
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 98 deletions.
7 changes: 7 additions & 0 deletions src/core/lombok/javac/HandlerLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public boolean isEvenIfAlreadyHandled() {
}

private SortedSet<Long> priorities;
private SortedSet<Long> prioritiesRequiringNoResolution;
private SortedSet<Long> prioritiesRequiringResolutionReset;

public SortedSet<Long> getPriorities() {
Expand All @@ -137,6 +138,10 @@ public SortedSet<Long> getPrioritiesRequiringResolutionReset() {
return prioritiesRequiringResolutionReset;
}

public SortedSet<Long> getPrioritiesRequiringNoResolution() {
return prioritiesRequiringNoResolution;
}

private void calculatePriorities() {
SortedSet<Long> set = new TreeSet<Long>();
SortedSet<Long> resetNeeded = new TreeSet<Long>();
Expand All @@ -152,6 +157,8 @@ private void calculatePriorities() {
}
this.priorities = Collections.unmodifiableSortedSet(set);
this.prioritiesRequiringResolutionReset = Collections.unmodifiableSortedSet(resetNeeded);
set.removeAll(resetNeeded);
this.prioritiesRequiringNoResolution = Collections.unmodifiableSortedSet(set);
}

/**
Expand Down
47 changes: 32 additions & 15 deletions src/core/lombok/javac/JavacTransformer.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2019 The Project Lombok Authors.
* Copyright (C) 2009-2023 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand All @@ -21,8 +21,10 @@
*/
package lombok.javac;

import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.SortedSet;
import java.util.Set;

import javax.annotation.processing.Messager;

Expand All @@ -42,30 +44,45 @@
public class JavacTransformer {
private final HandlerLibrary handlers;
private final Messager messager;
private final CleanupRegistry cleanup;

public JavacTransformer(Messager messager, Trees trees) {
public JavacTransformer(Messager messager, Trees trees, CleanupRegistry cleanup) {
this.messager = messager;
this.handlers = HandlerLibrary.load(messager, trees);
this.cleanup = cleanup;
}

public SortedSet<Long> getPriorities() {
return handlers.getPriorities();
}

public SortedSet<Long> getPrioritiesRequiringResolutionReset() {
return handlers.getPrioritiesRequiringResolutionReset();
}

public void transform(long priority, Context context, List<JCCompilationUnit> compilationUnits, CleanupRegistry cleanup) {
public void transform(Context context, List<JCCompilationUnit> compilationUnits) {
if (compilationUnits.isEmpty()) {
return;
}
JavacAST.ErrorLog errorLog = JavacAST.ErrorLog.create(messager, context);
Set<JCCompilationUnit> skip = Collections.newSetFromMap(new IdentityHashMap<JCCompilationUnit, Boolean>());
// Step 1: Run all normal handlers file by file
for (JCCompilationUnit unit : compilationUnits) {
if (!Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, JavacAST.getAbsoluteFileLocation(unit)))) {
if (Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, JavacAST.getAbsoluteFileLocation(unit)))) {
skip.add(unit);
continue;
}

JavacAST ast = new JavacAST(errorLog, context, unit, cleanup);
for (Long prio : handlers.getPrioritiesRequiringNoResolution()) {
ast.traverse(new AnnotationVisitor(prio));
handlers.callASTVisitors(ast, prio);
}
if (ast.isChanged()) LombokOptions.markChanged(context, (JCCompilationUnit) ast.top().get());
}

// Step 2: Run all resolution based handlers priority by priority
for (Long prio : handlers.getPrioritiesRequiringResolutionReset()) {
for (JCCompilationUnit unit : compilationUnits) {
if (skip.contains(unit)) {
continue;
}

JavacAST ast = new JavacAST(errorLog, context, unit, cleanup);
ast.traverse(new AnnotationVisitor(priority));
handlers.callASTVisitors(ast, priority);
ast.traverse(new AnnotationVisitor(prio));
handlers.callASTVisitors(ast, prio);
if (ast.isChanged()) LombokOptions.markChanged(context, (JCCompilationUnit) ast.top().get());
}
}
Expand Down
92 changes: 9 additions & 83 deletions src/core/lombok/javac/apt/LombokProcessor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2020 The Project Lombok Authors.
* Copyright (C) 2009-2023 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -29,13 +29,12 @@
import java.lang.reflect.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
Expand Down Expand Up @@ -80,6 +79,7 @@ public class LombokProcessor extends AbstractProcessor {
private JavacTransformer transformer;
private Trees trees;
private boolean lombokDisabled = false;
private CleanupRegistry cleanup = new CleanupRegistry();

/** {@inheritDoc} */
@Override public void init(ProcessingEnvironment procEnv) {
Expand All @@ -95,17 +95,7 @@ public class LombokProcessor extends AbstractProcessor {

placePostCompileAndDontMakeForceRoundDummiesHook();
trees = Trees.instance(javacProcessingEnv);
transformer = new JavacTransformer(procEnv.getMessager(), trees);
SortedSet<Long> p = transformer.getPriorities();
if (p.isEmpty()) {
this.priorityLevels = new long[] {0L};
this.priorityLevelsRequiringResolutionReset = new HashSet<Long>();
} else {
this.priorityLevels = new long[p.size()];
int i = 0;
for (Long prio : p) this.priorityLevels[i++] = prio;
this.priorityLevelsRequiringResolutionReset = transformer.getPrioritiesRequiringResolutionReset();
}
transformer = new JavacTransformer(procEnv.getMessager(), trees, cleanup);
}

private static final String JPE = "com.sun.tools.javac.processing.JavacProcessingEnvironment";
Expand Down Expand Up @@ -287,11 +277,6 @@ private void stopJavacProcessingEnvironmentFromClosingOurClassloader() {
}
}

private final IdentityHashMap<JCCompilationUnit, Long> roots = new IdentityHashMap<JCCompilationUnit, Long>();
private long[] priorityLevels;
private Set<Long> priorityLevelsRequiringResolutionReset;
private CleanupRegistry cleanup = new CleanupRegistry();

/** {@inheritDoc} */
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (lombokDisabled) return false;
Expand All @@ -300,73 +285,14 @@ private void stopJavacProcessingEnvironmentFromClosingOurClassloader() {
return false;
}

// We have: A sorted set of all priority levels: 'priorityLevels'

// Step 1: Take all CUs which aren't already in the map. Give them the first priority level.

Set<JCCompilationUnit> knownCus = Collections.newSetFromMap(new IdentityHashMap<JCCompilationUnit, Boolean>());
List<JCCompilationUnit> cusForThisRound = new ArrayList<JCCompilationUnit>();
for (Element element : roundEnv.getRootElements()) {
JCCompilationUnit unit = toUnit(element);
if (unit == null) continue;
if (roots.containsKey(unit)) continue;
roots.put(unit, priorityLevels[0]);
}

while (true) {
// Step 2: For all CUs (in the map, not the roundEnv!), run them across all handlers at their current prio level.

for (long prio : priorityLevels) {
List<JCCompilationUnit> cusForThisRound = new ArrayList<JCCompilationUnit>();
for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
Long prioOfCu = entry.getValue();
if (prioOfCu == null || prioOfCu != prio) continue;
cusForThisRound.add(entry.getKey());
}
transformer.transform(prio, javacProcessingEnv.getContext(), cusForThisRound, cleanup);
}

// Step 3: Push up all CUs to the next level. Set level to null if there is no next level.

Set<Long> newLevels = new HashSet<Long>();
for (int i = priorityLevels.length - 1; i >= 0; i--) {
Long curLevel = priorityLevels[i];
Long nextLevel = (i == priorityLevels.length - 1) ? null : priorityLevels[i + 1];
List<JCCompilationUnit> cusToAdvance = new ArrayList<JCCompilationUnit>();
for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
if (curLevel.equals(entry.getValue())) {
cusToAdvance.add(entry.getKey());
newLevels.add(nextLevel);
}
}
for (JCCompilationUnit unit : cusToAdvance) {
roots.put(unit, nextLevel);
}
}
newLevels.remove(null);

// Step 4: If ALL values are null, quit. Else, either do another loop right now or force a resolution reset by forcing a new round in the annotation processor.

if (newLevels.isEmpty()) return false;
newLevels.retainAll(priorityLevelsRequiringResolutionReset);
if (!newLevels.isEmpty()) {
// Force a new round to reset resolution. The next round will cause this method (process) to be called again.
forceNewRound(javacFiler);
return false;
}
// None of the new levels need resolution, so just keep going.
}
}

private int dummyCount = 0;
private void forceNewRound(JavacFiler filer) {
if (!filer.newFiles()) {
try {
filer.getGeneratedSourceNames().add("lombok.dummy.ForceNewRound" + (dummyCount++));
} catch (Exception e) {
e.printStackTrace();
processingEnv.getMessager().printMessage(Kind.WARNING,
"Can't force a new processing round. Lombok won't work.");
}
if (unit != null && knownCus.add(unit)) cusForThisRound.add(unit);
}
transformer.transform(javacProcessingEnv.getContext(), cusForThisRound);
return false;
}

private JCCompilationUnit toUnit(Element element) {
Expand Down

0 comments on commit 0751ddc

Please sign in to comment.