Skip to content

Commit b20f678

Browse files
authored
Road grading (#34)
Signed-off-by: Laird Nelson <ljnelson@gmail.com>
1 parent e12ee84 commit b20f678

16 files changed

Lines changed: 1392 additions & 375 deletions

README.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
The microBean™ Construct project provides classes and interfaces assisting with Java constructs such as types and
66
elements.
77

8+
Among other things, this project enables constructs modeled by the `javax.lang.model.*` packages to be accessed at
9+
runtime in a thread-safe manner. This permits the same constructs to be used at build time (e.g. by annotation
10+
processors) and at runtime (e.g. by tools and environments that need to perform reflection-like activities without
11+
actually loading and initializing classes), using only official and sanctioned APIs.
12+
813
# Status
914

1015
This project is currently experimental, in a pre-alpha state, and unsuitable for production use.
@@ -20,8 +25,8 @@ microBean™ Construct requires a Java runtime of version 21 or higher.
2025

2126
# Installation
2227

23-
microBean™ Construct is, or will be, available on [Maven Central](https://search.maven.org/). Include microBean™ Construct
24-
as a Maven dependency:
28+
microBean™ Construct is available on [Maven Central](https://search.maven.org/). Include microBean™ Construct as a Maven
29+
dependency:
2530

2631
```xml
2732
<dependency>
@@ -31,11 +36,17 @@ as a Maven dependency:
3136
Always check https://search.maven.org/artifact/org.microbean/microbean-construct
3237
for up-to-date available versions.
3338
-->
34-
<version>0.0.18</version>
39+
<version>0.0.19</version>
3540
</dependency>
3641
```
3742

3843
# Documentation
3944

40-
Full documentation is, or will be, available at
45+
Full documentation is available at
4146
[microbean.github.io/microbean-construct](https://microbean.github.io/microbean-construct/).
47+
48+
# References
49+
50+
* This project is tangentially and purely coincidentally related to [JEP 119](https://openjdk.org/jeps/119).
51+
* A seemingly shelved attempt to implement the `javax.lang.model.*` constructs in terms of reflective constructs can be
52+
found in [JDK-8004133](https://bugs.openjdk.org/browse/JDK-8004133).

src/main/java/org/microbean/construct/BlockingCompilationTask.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,20 @@ public final void close() {
130130
}
131131
}
132132

133+
/**
134+
* Overrides {@link CompletableFuture#completeExceptionally(Throwable)} to additionally {@linkplain #close() close}
135+
* this {@link BlockingCompilationTask}.
136+
*
137+
* @param t a {@link Throwable}; see {@link CompletableFuture#completeExceptionally(Throwable)} for additional
138+
* contractual obligations
139+
*
140+
* @return the result of invoking {@link CompletableFuture#completeExceptionally(Throwable)} with the supplied {@link
141+
* Throwable}
142+
*
143+
* @see #close()
144+
*
145+
* @see CompletableFuture#completeExceptionally(Throwbale)
146+
*/
133147
@Override // CompletableFuture<ProcessingEnvironment>
134148
public final boolean completeExceptionally(final Throwable t) {
135149
final boolean result = super.completeExceptionally(t);
@@ -185,8 +199,7 @@ public final void run() {
185199
task.addModules(additionalRootModuleNames);
186200

187201
// Set the task's annotation processor whose only function will be to return the ProcessingEnvironment supplied to
188-
// it in its #init(ProcessingEnvironment) method. The supplied latch is used to make this task block forever (unless
189-
// an error occurs) to keep the ProcessingEnvironment "in scope".
202+
// it in its #init(ProcessingEnvironment) method.
190203
task.setProcessors(List.of(this.p));
191204

192205
if (LOGGER.isLoggable(DEBUG)) {
@@ -196,8 +209,8 @@ public final void run() {
196209
}
197210

198211
try {
199-
final Boolean result = task.call(); // blocks forever deliberately unless an error occurs; see Processor2
200-
if (!TRUE.equals(result)) {
212+
final Boolean result = task.call(); // blocks forever deliberately unless an error occurs; see Processor
213+
if (!TRUE.equals(result)) { // (result could be null, technically speaking)
201214
if (LOGGER.isLoggable(ERROR)) {
202215
LOGGER.log(ERROR, "Calling CompilationTask failed");
203216
}

src/main/java/org/microbean/construct/Processor.java

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import java.lang.System.Logger;
1717

1818
import java.util.List;
19-
import java.util.Objects;
2019
import java.util.Set;
2120

2221
import java.util.concurrent.locks.Condition;
@@ -38,26 +37,55 @@
3837

3938
import static java.lang.System.getLogger;
4039

40+
import static java.util.Objects.requireNonNull;
41+
4142
final class Processor implements AutoCloseable, javax.annotation.processing.Processor {
4243

4344
private static final Logger LOGGER = getLogger(Processor.class.getName());
4445

46+
// @GuardedBy("lock")
4547
private final Consumer<? super ProcessingEnvironment> cpe;
4648

49+
// @GuardedBy("lock")
4750
// run() method invoked under lock
4851
private final Runnable r;
4952

5053
private final Lock lock;
5154

55+
// @GuardedBy("lock")
5256
private final Condition c;
5357

5458
// @GuardedBy("lock")
5559
private boolean closed;
5660

57-
Processor(final Consumer<? super ProcessingEnvironment> cpe,
58-
final Runnable r) {
61+
/**
62+
* Creates a new {@link Processor}.
63+
*
64+
* <p>This {@link Processor} will be invoked by a {@link BlockingCompilationTask} as part of an invocation of its
65+
* {@link BlockingCompilationTask#run()} method. Its {@link #init(ProcessingEnvironment)} method will be invoked as
66+
* part of {@linkplain javax.annotation.processing.Processor the standard <code>Processor</code> lifecycle}. It will
67+
* call the {@link Consumer#accept(Object) accept(ProcessingEnvironment)} method on the supplied {@link
68+
* Consumer}. Then it will block until {@link #close()} is invoked (from a separate thread, obviously). Before
69+
* exiting, it will invoke the {@link Runnable#run() run()} method of the supplied {@link Runnable}.</p>
70+
*
71+
* @param cpe a {@link Consumer} of {@link ProcessingEnvironment} instances, typically {@link
72+
* BlockingCompilationTask#complete(Object)}; must not be {@code null}
73+
*
74+
* @param r a {@link Runnable} that is invoked at the conclusion of an invocation of the {@link
75+
* #init(ProcessingEnvironment)} method; may be {@code null}
76+
*
77+
* @see #init(ProcessingEnvironment)
78+
*
79+
* @see #close()
80+
*
81+
* @see BlockingCompilationTask
82+
*
83+
* @see javax.annotation.processing.Processor
84+
*/
85+
Processor(final Consumer<? super ProcessingEnvironment> cpe, // usually BlockingCompliationTask::complete
86+
final Runnable r) { // usually BlockingCompliationTask::obtrudeException
5987
super();
60-
this.cpe = Objects.requireNonNull(cpe, "cpe");
88+
this.cpe = requireNonNull(cpe, "cpe");
6189
this.r = r == null ? Processor::sink : r;
6290
this.lock = new ReentrantLock();
6391
this.c = this.lock.newCondition();
@@ -83,12 +111,15 @@ public final void close() {
83111
}
84112

85113
/**
86-
* Initializes this {@link Processor}.
114+
* Initializes this {@link Processor} by calling the {@link Consumer#accept(Object) accept(Object)} method on the
115+
* {@link Consumer} {@linkplain #Processor(Consumer, Runnable) supplied at construction time} with the supplied {@link
116+
* ProcessingEnvironment}, <strong>and then blocking until another thread invokes the {@link #close()}
117+
* method</strong>.
87118
*
88119
* @param pe a {@link ProcessingEnvironment}; must not be {@code null}
89120
*
90121
* @deprecated This method should be called only by a Java compiler in accordance with annotation processing
91-
* contracts.
122+
* contracts. All other usage will result in undefined behavior.
92123
*/
93124
@Deprecated // to be called only by a Java compiler in accordance with annotation processing contracts
94125
@Override // Processor;
@@ -108,6 +139,21 @@ public final void init(final ProcessingEnvironment pe) {
108139
}
109140
}
110141

142+
/**
143+
* Returns an {@linkplain List#of() empty, immutable, determinate <code>List</code>} when invoked, regardless of
144+
* arguments.
145+
*
146+
* @param element ignored; may be {@code null}
147+
*
148+
* @param annotation ignored; may be {@code null}
149+
*
150+
* @param member ignored; may be {@code null}
151+
*
152+
* @param userText ignored; may be {@code null}
153+
*
154+
* @return an {@linkplain List#of() empty, immutable, determinate <code>List</code>} when invoked, regardless of
155+
* arguments
156+
*/
111157
@Override // Processor
112158
public final Iterable<? extends Completion> getCompletions(final Element element,
113159
final AnnotationMirror annotation,
@@ -116,21 +162,43 @@ public final Iterable<? extends Completion> getCompletions(final Element element
116162
return List.of();
117163
}
118164

165+
/**
166+
* Returns an {@linkplain Set#of() empty, immutable, determinate <code>Set</code>} when invoked.
167+
*
168+
* @return an {@linkplain Set#of() empty, immutable, determinate <code>Set</code>} when invoked
169+
*/
119170
@Override // Processor
120171
public final Set<String> getSupportedAnnotationTypes() {
121172
return Set.of();
122173
}
123174

175+
/**
176+
* Returns an {@linkplain Set#of() empty, immutable, determinate <code>Set</code>} when invoked.
177+
*
178+
* @return an {@linkplain Set#of() empty, immutable, determinate <code>Set</code>} when invoked
179+
*/
124180
@Override // Processor
125181
public final Set<String> getSupportedOptions() {
126182
return Set.of();
127183
}
128184

185+
/**
186+
* Returns the return value of an invocation of the {@link SourceVersion#latestSupported()} method when invoked.
187+
*
188+
* @return the return value of an invocation of the {@link SourceVersion#latestSupported()} method when invoked
189+
*/
129190
@Override // Processor
130191
public final SourceVersion getSupportedSourceVersion() {
131192
return SourceVersion.latestSupported();
132193
}
133194

195+
/**
196+
* Returns {@code false} when invoked, regardless of arguments.
197+
*
198+
* @param annotations ignored; may be {@code null}
199+
*
200+
* @param roundEnvironment ignored; may be {@code null}
201+
*/
134202
@Override // Processor
135203
public final boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) {
136204
return false;

0 commit comments

Comments
 (0)