001/* 002 * Copyright (C) 2022 Ashley Scopes 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.github.ascopes.jct.compilers; 017 018import static io.github.ascopes.jct.utils.IterableUtils.requireAtLeastOne; 019 020import io.github.ascopes.jct.ex.JctCompilerException; 021import io.github.ascopes.jct.filemanagers.AnnotationProcessorDiscovery; 022import io.github.ascopes.jct.filemanagers.LoggingMode; 023import io.github.ascopes.jct.workspaces.Workspace; 024import java.io.UncheckedIOException; 025import java.nio.charset.Charset; 026import java.nio.charset.StandardCharsets; 027import java.util.Collection; 028import java.util.List; 029import java.util.Locale; 030import java.util.Set; 031import javax.annotation.processing.Processor; 032import javax.lang.model.SourceVersion; 033import org.jspecify.annotations.Nullable; 034 035/** 036 * Base definition of a compiler that can be configured to perform a compilation run against 037 * sources. 038 * 039 * <p>JctCompiler objects are often a nexus that will manage configuring an underlying JSR-199 040 * compiler internally in a platform-agnostic way. 041 * 042 * @author Ashley Scopes 043 * @since 0.0.1 044 */ 045public interface JctCompiler { 046 047 /** 048 * Default setting for deprecation warnings ({@code true}). 049 */ 050 boolean DEFAULT_SHOW_DEPRECATION_WARNINGS = true; 051 052 /** 053 * Default setting for locale ({@link Locale#ROOT}). 054 */ 055 Locale DEFAULT_LOCALE = Locale.ROOT; 056 057 /** 058 * Default setting for preview features ({@code false}). 059 */ 060 boolean DEFAULT_PREVIEW_FEATURES = false; 061 062 /** 063 * Default setting for verbose logging ({@code false}). 064 */ 065 boolean DEFAULT_VERBOSE = false; 066 067 /** 068 * Default setting for displaying warnings ({@code true}). 069 */ 070 boolean DEFAULT_SHOW_WARNINGS = true; 071 072 /** 073 * Default setting for displaying warnings as errors ({@code false}). 074 */ 075 boolean DEFAULT_FAIL_ON_WARNINGS = false; 076 077 /** 078 * Default setting for fixing modules being placed on the classpath by mistake ({@code true}). 079 */ 080 boolean DEFAULT_FIX_JVM_MODULE_PATH_MISMATCH = true; 081 082 /** 083 * Default setting for inclusion of the current class path ({@code true}). 084 */ 085 boolean DEFAULT_INHERIT_CLASS_PATH = true; 086 087 /** 088 * Default setting for inclusion of the current module path ({@code true}). 089 */ 090 boolean DEFAULT_INHERIT_MODULE_PATH = true; 091 092 /** 093 * Default setting for inclusion of the system module path ({@code true}). 094 */ 095 boolean DEFAULT_INHERIT_SYSTEM_MODULE_PATH = true; 096 097 /** 098 * Default setting for logging file manager operations ({@link LoggingMode#DISABLED}). 099 */ 100 LoggingMode DEFAULT_FILE_MANAGER_LOGGING_MODE = LoggingMode.DISABLED; 101 102 /** 103 * Default setting for logging diagnostics ({@link LoggingMode#ENABLED}). 104 */ 105 LoggingMode DEFAULT_DIAGNOSTIC_LOGGING_MODE = LoggingMode.ENABLED; 106 107 /** 108 * Default setting for the compilation mode to use 109 * ({@link CompilationMode#COMPILATION_AND_ANNOTATION_PROCESSING}). 110 */ 111 CompilationMode DEFAULT_COMPILATION_MODE = CompilationMode.COMPILATION_AND_ANNOTATION_PROCESSING; 112 113 /** 114 * Default setting for how to apply annotation processor discovery when no processors are 115 * explicitly defined ({@link AnnotationProcessorDiscovery#INCLUDE_DEPENDENCIES}). 116 */ 117 AnnotationProcessorDiscovery DEFAULT_ANNOTATION_PROCESSOR_DISCOVERY = 118 AnnotationProcessorDiscovery.INCLUDE_DEPENDENCIES; 119 120 /** 121 * Default charset to use for compiler logs ({@link StandardCharsets#UTF_8}). 122 */ 123 Charset DEFAULT_LOG_CHARSET = StandardCharsets.UTF_8; 124 125 /** 126 * Default debugging info to include in the compilation (all possible info). 127 */ 128 Set<DebuggingInfo> DEFAULT_DEBUGGING_INFO = DebuggingInfo.all(); 129 130 /** 131 * Default preference for including reflective parameter information in compiled classes 132 * ({@code true}). 133 */ 134 boolean DEFAULT_PARAMETER_INFO_ENABLED = true; 135 136 /** 137 * Invoke the compilation and return the compilation result. 138 * 139 * <p>The actual classes to compile will be dynamically discovered. If you wish to 140 * specify the specific classes to compile, see {@link #compile(Workspace, String...)} or 141 * {@link #compile(Workspace, Collection)}. 142 * 143 * @param workspace the workspace to compile. 144 * @return the compilation result. 145 * @throws JctCompilerException if the compiler threw an unhandled exception. This should not 146 * occur for compilation failures generally. 147 * @throws IllegalStateException if no compilation units were found. 148 * @throws UncheckedIOException if an IO error occurs. 149 * @see #compile(Workspace, String...) 150 * @see #compile(Workspace, Collection) 151 */ 152 JctCompilation compile(Workspace workspace); 153 154 /** 155 * Invoke the compilation and return the compilation result. 156 * 157 * <p>Only classes matching the given class names will be compiled. 158 * 159 * <p>If you wish to let JCT determine which classes to compile dynamically, see 160 * {@link #compile(Workspace)} instead. 161 * 162 * <p>Note that nested instance/static nested classes cannot be specified individually 163 * here. To compile them, you must also compile their outer class that they are defined within. 164 * 165 * @param workspace the workspace to compile. 166 * @param classNames the class names to compile. 167 * @return the compilation result. 168 * @throws JctCompilerException if the compiler threw an unhandled exception. This should not 169 * occur for compilation failures generally. 170 * @throws NullPointerException if any class names are null, or if the array is null. 171 * @throws IllegalStateException if no compilation units were found. 172 * @throws UncheckedIOException if an IO error occurs. 173 * @see #compile(Workspace) 174 * @see #compile(Workspace, Collection) 175 */ 176 default JctCompilation compile(Workspace workspace, String... classNames) { 177 requireAtLeastOne(classNames, "classNames"); 178 return compile(workspace, List.of(classNames)); 179 } 180 181 /** 182 * Invoke the compilation and return the compilation result. 183 * 184 * <p>Only classes matching the given class names will be compiled. 185 * 186 * <p>If you wish to let JCT determine which classes to compile dynamically, see 187 * {@link #compile(Workspace)} instead. 188 * 189 * <p>Note that nested instance/static nested classes cannot be specified individually 190 * here. To compile them, you must also compile their outer class that they are defined within. 191 * 192 * @param workspace the workspace to compile. 193 * @param classNames the class names to compile. 194 * @return the compilation result. 195 * @throws JctCompilerException if the compiler threw an unhandled exception. This should not 196 * occur for compilation failures usually. 197 * @throws NullPointerException if the {@code classNames} collection contains any null values, 198 * or if the collection itself is null. 199 * @throws IllegalArgumentException if the collection is empty. 200 * @throws IllegalStateException if no compilation units were found. 201 * @throws UncheckedIOException if an IO error occurs. 202 * @see #compile(Workspace) 203 * @see #compile(Workspace, String...) 204 */ 205 JctCompilation compile(Workspace workspace, Collection<String> classNames); 206 207 /** 208 * Apply a given configurer to this compiler. 209 * 210 * <p>Configurers can be lambdas, method references, or objects. 211 * 212 * <pre><code> 213 * // Using an object configurer 214 * var werrorConfigurer = new JctCompilerConfigurer<RuntimeException>() { 215 * {@literal @Override} 216 * public void configure(JctCompiler compiler) { 217 * compiler.failOnWarnings(true); 218 * } 219 * }; 220 * compiler.configure(werrorConfigurer); 221 * 222 * // Using a lambda configurer 223 * compiler.configure(c -> c.verbose(true)); 224 * </code></pre> 225 * 226 * <p>Configurers take a type parameter that corresponds to an exception type. This 227 * is the exception type that can be thrown by the configurer, or {@link RuntimeException} if no 228 * checked exception is thrown. This mechanism allows configurers to propagate checked exceptions 229 * to their caller where needed. 230 * 231 * <pre><code> 232 * class FileFlagConfigurer implements JctCompilerConfigurer<IOException> { 233 * private final Path path; 234 * 235 * public FileFlagConfigurer(String... path) { 236 * this(Path.of(path)); 237 * } 238 * 239 * public FileFlagConfigurer(Path path) { 240 * this.path = path; 241 * } 242 * 243 * {@literal @Override} 244 * public void configure(JctCompiler compiler) throws IOException { 245 * var flags = Files.lines(path) 246 * .map(String::trim) 247 * .filter(not(String::isBlank)) 248 * .toList(); 249 * compiler.addCompilerOptions(flags); 250 * } 251 * } 252 * 253 * {@literal @Test} 254 * void testSomething() throws IOException { 255 * ... 256 * compiler.configure(new FileFlagConfigurer("src", "test", "resources", "flags.txt")); 257 * ... 258 * } 259 * </code></pre> 260 * 261 * @param <E> any exception that may be thrown. 262 * @param configurer the configurer to invoke. 263 * @return this compiler object for further call chaining. 264 * @throws E any exception that may be thrown by the configurer. If no checked exception is 265 * thrown, then this should be treated as {@link RuntimeException}. 266 */ 267 <E extends Exception> JctCompiler configure(JctCompilerConfigurer<E> configurer) throws E; 268 269 /** 270 * Get the friendly printable name of this compiler object. 271 * 272 * @return the name of the compiler. 273 */ 274 String getName(); 275 276 /** 277 * Set the friendly name of this compiler. 278 * 279 * <p>This will be used by the 280 * {@link io.github.ascopes.jct.junit.JavacCompilerTest JUnit5 support} to name unit test cases. 281 * 282 * @param name the name to set. 283 * @return this compiler object for further call chaining. 284 */ 285 JctCompiler name(String name); 286 287 /** 288 * Get an <strong>immutable snapshot view</strong> of the current annotation processor options 289 * that are set. 290 * 291 * @return the current annotation processor options that are set. 292 */ 293 List<String> getAnnotationProcessorOptions(); 294 295 /** 296 * Add options to pass to any annotation processors. 297 * 298 * @param annotationProcessorOptions the options to pass. 299 * @return this compiler object for further call chaining. 300 */ 301 JctCompiler addAnnotationProcessorOptions(Iterable<String> annotationProcessorOptions); 302 303 /** 304 * Add options to pass to any annotation processors. 305 * 306 * @param annotationProcessorOptions options to pass. 307 * @return this compiler object for further call chaining. 308 */ 309 default JctCompiler addAnnotationProcessorOptions(String... annotationProcessorOptions) { 310 return addAnnotationProcessorOptions(List.of(annotationProcessorOptions)); 311 } 312 313 /** 314 * Get an <strong>immutable snapshot view</strong> of the current annotation processors that are 315 * explicitly set to be run, in the order that they were provided to the compiler. 316 * 317 * @return the current annotation processors that are set. 318 */ 319 List<Processor> getAnnotationProcessors(); 320 321 /** 322 * Add annotation processors to invoke. 323 * 324 * <p><strong>Warning:</strong> This bypasses the discovery process of annotation processors 325 * provided in the annotation processor path and annotation processor module paths, as well as any 326 * other locations such as class paths and module paths. 327 * 328 * @param annotationProcessors the processors to invoke. 329 * @return this compiler object for further call chaining. 330 */ 331 JctCompiler addAnnotationProcessors(Iterable<? extends Processor> annotationProcessors); 332 333 /** 334 * Add annotation processors to invoke. 335 * 336 * <p><strong>Warning:</strong> This bypasses the discovery process of annotation processors 337 * provided in the annotation processor path and annotation processor module paths, as well as any 338 * other locations such as class paths and module paths. 339 * 340 * @param annotationProcessors processors to invoke. 341 * @return this compiler object for further call chaining. 342 */ 343 default JctCompiler addAnnotationProcessors(Processor... annotationProcessors) { 344 return addAnnotationProcessors(List.of(annotationProcessors)); 345 } 346 347 /** 348 * Get an <strong>immutable snapshot view</strong> of the current compiler options that are set. 349 * 350 * @return the current compiler options that are set. 351 */ 352 List<String> getCompilerOptions(); 353 354 /** 355 * Add command line options to pass to {@code javac}. 356 * 357 * @param compilerOptions the options to add. 358 * @return this compiler object for further call chaining. 359 */ 360 JctCompiler addCompilerOptions(Iterable<String> compilerOptions); 361 362 /** 363 * Add command line options to pass to {@code javac}. 364 * 365 * @param compilerOptions options to add. 366 * @return this compiler object for further call chaining. 367 */ 368 default JctCompiler addCompilerOptions(String... compilerOptions) { 369 return addCompilerOptions(List.of(compilerOptions)); 370 } 371 372 /** 373 * Determine whether verbose logging is enabled or not. 374 * 375 * <p>Unless otherwise changed or specified, implementations should default to 376 * {@link #DEFAULT_VERBOSE}. 377 * 378 * <p>Note that enabling this is compiler-specific behaviour. There is no guarantee that the 379 * output target or the format or verbosity of output will be consistent between different 380 * compiler implementations. 381 * 382 * @return whether verbose logging is enabled or not. 383 */ 384 boolean isVerbose(); 385 386 /** 387 * Set whether to use verbose output or not. 388 * 389 * <p>Unless otherwise changed or specified, implementations should default to 390 * {@link #DEFAULT_VERBOSE}. 391 * 392 * <p>Note that enabling this is compiler-specific behaviour. There is no guarantee that the 393 * output target or the format or verbosity of output will be consistent between different 394 * compiler implementations. 395 * 396 * @param enabled {@code true} for verbose output, {@code false} for normal output. 397 * @return this compiler for further call chaining. 398 */ 399 JctCompiler verbose(boolean enabled); 400 401 /** 402 * Determine whether preview features are enabled or not. 403 * 404 * <p>Unless otherwise changed or specified, implementations should default to 405 * {@link #DEFAULT_PREVIEW_FEATURES}. 406 * 407 * @return whether preview features are enabled or not. 408 */ 409 boolean isPreviewFeatures(); 410 411 /** 412 * Set whether to enable compiler preview features or not. 413 * 414 * <p>Unless otherwise changed or specified, implementations should default to 415 * {@link #DEFAULT_PREVIEW_FEATURES}. 416 * 417 * <p>Generally, this feature should be avoided if testing across multiple versions 418 * of Java, as preview features are often not finalised and may change without warning. 419 * 420 * @param enabled {@code true} to enable preview features, or {@code false} to disable them. 421 * @return this compiler object for further call chaining. 422 */ 423 JctCompiler previewFeatures(boolean enabled); 424 425 /** 426 * Determine whether warnings are enabled or not. 427 * 428 * <p>Unless otherwise changed or specified, implementations should default to 429 * {@link #DEFAULT_SHOW_WARNINGS}. 430 * 431 * @return whether warnings are enabled or not. 432 */ 433 boolean isShowWarnings(); 434 435 /** 436 * Set whether to enable displaying warnings or not. 437 * 438 * <p>Unless otherwise changed or specified, implementations should default to 439 * {@link #DEFAULT_SHOW_WARNINGS}. 440 * 441 * @param enabled {@code true} to enable warnings. {@code false} to disable them. 442 * @return this compiler object for further call chaining. 443 */ 444 JctCompiler showWarnings(boolean enabled); 445 446 /** 447 * Determine whether deprecation warnings are enabled or not. 448 * 449 * <p>Unless otherwise changed or specified, implementations should default to 450 * {@link #DEFAULT_SHOW_DEPRECATION_WARNINGS}. 451 * 452 * @return whether deprecation warnings are enabled or not. 453 */ 454 boolean isShowDeprecationWarnings(); 455 456 /** 457 * Set whether to enable deprecation warnings or not. 458 * 459 * <p>This is ignored if {@link #showWarnings(boolean)} is disabled. 460 * 461 * <p>Unless otherwise changed or specified, implementations should default to 462 * {@link #DEFAULT_SHOW_DEPRECATION_WARNINGS}. 463 * 464 * @param enabled {@code true} to enable deprecation warnings. {@code false} to disable them. 465 * @return this compiler object for further call chaining. 466 */ 467 JctCompiler showDeprecationWarnings(boolean enabled); 468 469 /** 470 * Determine whether warnings are being treated as errors or not. 471 * 472 * <p>Unless otherwise changed or specified, implementations should default to 473 * {@link #DEFAULT_FAIL_ON_WARNINGS}. 474 * 475 * @return whether warnings are being treated as errors or not. 476 */ 477 boolean isFailOnWarnings(); 478 479 /** 480 * Set whether to enable treating warnings as errors or not. 481 * 482 * <p>Some compilers may call this flag something different, such as "{@code -Werror}". 483 * 484 * <p>This is ignored if {@link #showWarnings(boolean)} is disabled. 485 * 486 * <p>Unless otherwise changed or specified, implementations should default to 487 * {@link #DEFAULT_FAIL_ON_WARNINGS}. 488 * 489 * @param enabled {@code true} to enable treating warnings as errors. {@code false} to disable 490 * them. 491 * @return this compiler object for further call chaining. 492 */ 493 JctCompiler failOnWarnings(boolean enabled); 494 495 /** 496 * Get the compilation mode that is in use. 497 * 498 * <p>Unless otherwise changed or specified, implementations should default to 499 * {@link #DEFAULT_COMPILATION_MODE}. 500 * 501 * @return the compilation mode. 502 */ 503 CompilationMode getCompilationMode(); 504 505 /** 506 * Set the compilation mode to use for this compiler. 507 * 508 * <p>This allows you to override whether sources are compiled or annotation-processed 509 * without running the full compilation process. Tuning this may provide faster test cases in some 510 * situations. 511 * 512 * <p>Unless otherwise changed or specified, implementations should default to 513 * {@link #DEFAULT_COMPILATION_MODE}. 514 * 515 * @param compilationMode the compilation mode to use. 516 * @return this compiler object for further call chaining. 517 */ 518 JctCompiler compilationMode(CompilationMode compilationMode); 519 520 /** 521 * Get the default release to use if no release or target version is specified. 522 * 523 * <p>This can <strong>not</strong> be configured generally, as it is defined by 524 * the internal compiler implementation. 525 * 526 * <p>Generally, this value will be an integer within a string. The value is 527 * represented as a string to allow supporting compilers which may use non-integer version 528 * numbers. 529 * 530 * @return the default release version to use. 531 */ 532 String getDefaultRelease(); 533 534 /** 535 * Get the effective release to use for the actual compilation. 536 * 537 * <p>Generally, this value will be an integer within a string. The value is 538 * represented as a string to allow supporting compilers which may use non-integer version 539 * numbers. 540 * 541 * <p>This may be determined from the {@link #getSource() source}, 542 * {@link #getTarget() target}, {@link #getRelease() release}, and 543 * {@link #getDefaultRelease() default release.} 544 * 545 * @return the effective release. 546 */ 547 String getEffectiveRelease(); 548 549 /** 550 * Get the current release version that is set, or {@code null} if left to the compiler to decide. 551 * default. 552 * 553 * <p>Generally, this value will be an integer within a string. The value is 554 * represented as a string to allow supporting compilers which may use non-integer version 555 * numbers. 556 * 557 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 558 * default. 559 * 560 * @return the release version string, if set. 561 */ 562 @Nullable 563 String getRelease(); 564 565 /** 566 * Set the release version. 567 * 568 * <p>This will clear any source and target version that is set. 569 * 570 * <p>Generally, this value will be an integer within a string. The value is 571 * represented as a string to allow supporting compilers which may use non-integer version 572 * numbers. 573 * 574 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 575 * default. 576 * 577 * @param release the version to set. 578 * @return this compiler object for further call chaining. 579 */ 580 JctCompiler release(@Nullable String release); 581 582 /** 583 * Set the release version. 584 * 585 * <p>This will clear any source and target version that is set. 586 * 587 * <p>Generally, this value will be an integer within a string. The value is 588 * represented as a string to allow supporting compilers which may use non-integer version 589 * numbers. 590 * 591 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 592 * default. 593 * 594 * @param release the version to set. 595 * @return this compiler object for further call chaining. 596 * @throws IllegalArgumentException if the version is less than 0. 597 * @throws UnsupportedOperationException if the compiler does not support integer versions. 598 */ 599 default JctCompiler release(int release) { 600 if (release < 0) { 601 throw new IllegalArgumentException("Cannot provide a release version less than 0"); 602 } 603 604 return release(Integer.toString(release)); 605 } 606 607 /** 608 * Set the release version. 609 * 610 * <p>This will clear any source and target version that is set. 611 * 612 * <p>Generally, this value will be an integer within a string. The value is 613 * represented as a string to allow supporting compilers which may use non-integer version 614 * numbers. 615 * 616 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 617 * default. 618 * 619 * @param release the version to set. 620 * @return this compiler object for further call chaining. 621 * @throws UnsupportedOperationException if the compiler does not support integer versions. 622 * @throws NullPointerException if the release is null. 623 */ 624 625 default JctCompiler release(SourceVersion release) { 626 @SuppressWarnings("EnumOrdinal") 627 var ordinal = release.ordinal(); 628 return release(Integer.toString(ordinal)); 629 } 630 631 /** 632 * Request that the compiler uses a language version that corresponds to the runtime language 633 * version in use on the current JVM. 634 * 635 * <p>For example, running this on JRE 19 would set the release to "19". 636 * 637 * <p>This calls {@link #release(int)} internally. 638 * 639 * @return this compiler object for further call chaining. 640 * @throws UnsupportedOperationException if the current JVM version does not correspond to a 641 * supported Java release version in the compiler, or if the 642 * compiler does not support integral version numbers. 643 * @since 1.1.0 644 */ 645 default JctCompiler useRuntimeRelease() { 646 return release(Runtime.version().feature()); 647 } 648 649 /** 650 * Get the current source version that is set, or {@code null} if left to the compiler to decide. 651 * default. 652 * 653 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 654 * default. 655 * 656 * @return the source version string, if set. 657 */ 658 @Nullable 659 String getSource(); 660 661 /** 662 * Set the source version. 663 * 664 * <p>This will clear any release version that is set. 665 * 666 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 667 * default. 668 * 669 * <p>Source and target versions have mostly been replaced with the release version 670 * mechanism which controls both flags and can ensure other behaviours are consistent. This 671 * feature is still provided in case you have a specific use case that is not covered by this 672 * functionality. 673 * 674 * @param source the version to set. 675 * @return this compiler object for further call chaining. 676 */ 677 JctCompiler source(@Nullable String source); 678 679 /** 680 * Set the source version. 681 * 682 * <p>This will clear any release version that is set. 683 * 684 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 685 * default. 686 * 687 * <p>Source and target versions have mostly been replaced with the release version 688 * mechanism which controls both flags and can ensure other behaviours are consistent. This 689 * feature is still provided in case you have a specific use case that is not covered by this 690 * functionality. 691 * 692 * @param source the version to set. 693 * @return this compiler object for further call chaining. 694 * @throws IllegalArgumentException if the version is less than 0. 695 * @throws UnsupportedOperationException if the compiler does not support integer versions. 696 */ 697 default JctCompiler source(int source) { 698 if (source < 0) { 699 throw new IllegalArgumentException("Cannot provide a source version less than 0"); 700 } 701 702 return source(Integer.toString(source)); 703 } 704 705 /** 706 * Set the source version. 707 * 708 * <p>This will clear any release version that is set. 709 * 710 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 711 * default. 712 * 713 * <p>Source and target versions have mostly been replaced with the release version 714 * mechanism which controls both flags and can ensure other behaviours are consistent. This 715 * feature is still provided in case you have a specific use case that is not covered by this 716 * functionality. 717 * 718 * @param source the version to set. 719 * @return this compiler object for further call chaining. 720 * @throws UnsupportedOperationException if the compiler does not support integer versions. 721 * @throws NullPointerException if the source is null. 722 */ 723 default JctCompiler source(SourceVersion source) { 724 @SuppressWarnings("EnumOrdinal") 725 var ordinal = source.ordinal(); 726 return source(Integer.toString(ordinal)); 727 } 728 729 /** 730 * Get the current target version that is set, or {@code null} if left to the compiler default. 731 * 732 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 733 * default. 734 * 735 * @return the target version string, if set. 736 */ 737 @Nullable 738 String getTarget(); 739 740 /** 741 * Set the target version. 742 * 743 * <p>This will clear any release version that is set. 744 * 745 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 746 * default. 747 * 748 * <p>Source and target versions have mostly been replaced with the release version 749 * mechanism which controls both flags and can ensure other behaviours are consistent. This 750 * feature is still provided in case you have a specific use case that is not covered by this 751 * functionality. 752 * 753 * @param target the version to set. 754 * @return this compiler object for further call chaining. 755 */ 756 JctCompiler target(@Nullable String target); 757 758 /** 759 * Set the target version. 760 * 761 * <p>This will clear any release version that is set. 762 * 763 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 764 * default. 765 * 766 * <p>Source and target versions have mostly been replaced with the release version 767 * mechanism which controls both flags and can ensure other behaviours are consistent. This 768 * feature is still provided in case you have a specific use case that is not covered by this 769 * functionality. 770 * 771 * @param target the version to set. 772 * @return this compiler object for further call chaining. 773 * @throws IllegalArgumentException if the version is less than 0. 774 * @throws UnsupportedOperationException if the compiler does not support integer versions. 775 */ 776 default JctCompiler target(int target) { 777 if (target < 0) { 778 throw new IllegalArgumentException("Cannot provide a target version less than 0"); 779 } 780 781 return target(Integer.toString(target)); 782 } 783 784 /** 785 * Set the target version. 786 * 787 * <p>This will clear any release version that is set. 788 * 789 * <p>Unless explicitly defined, the default setting is expected to be a sane compiler-specific 790 * default. 791 * 792 * <p>Source and target versions have mostly been replaced with the release version 793 * mechanism which controls both flags and can ensure other behaviours are consistent. This 794 * feature is still provided in case you have a specific use case that is not covered by this 795 * functionality. 796 * 797 * @param target the version to set. 798 * @return this compiler object for further call chaining. 799 * @throws UnsupportedOperationException if the compiler does not support integer versions. 800 * @throws NullPointerException if the target is null. 801 */ 802 default JctCompiler target(SourceVersion target) { 803 @SuppressWarnings("EnumOrdinal") 804 var ordinal = target.ordinal(); 805 return target(Integer.toString(ordinal)); 806 } 807 808 /** 809 * Get whether we will attempt to fix modules appearing on the classpath, or non-modules appearing 810 * on the module path. 811 * 812 * <p>This enables correct classpath and module path detection when the test pack is a module but 813 * the code being compiled in the test is not, and vice versa. We need this because many build 814 * systems decide whether to populate the {@code --module-path} or the {@code --classpath} 815 * with JPMS-enabled dependencies based on whether the project under compilation is a JPMS module 816 * itself. 817 * 818 * <p>This only applies if {@link #isInheritModulePath()} or {@link #isInheritClassPath()} is 819 * enabled, and only applies to the current JVM classpath and module path. 820 * 821 * <p>Unless otherwise changed or specified, implementations should default to 822 * {@link #DEFAULT_FIX_JVM_MODULE_PATH_MISMATCH}. 823 * 824 * @return {@code true} if enabled, or {@code false} if disabled. 825 */ 826 boolean isFixJvmModulePathMismatch(); 827 828 /** 829 * Get whether we will attempt to fix modules appearing on the classpath, or non-modules appearing 830 * on the module path. 831 * 832 * <p>Unless otherwise changed or specified, implementations should default to 833 * {@link #DEFAULT_FIX_JVM_MODULE_PATH_MISMATCH}. 834 * 835 * @param fixJvmModulePathMismatch whether to enable the mismatch fixing or not. 836 * @return this compiler object for further call chaining. 837 */ 838 JctCompiler fixJvmModulePathMismatch(boolean fixJvmModulePathMismatch); 839 840 /** 841 * Get whether the class path is inherited from the active JVM or not. 842 * 843 * <p>Unless otherwise changed or specified, implementations should default to 844 * {@link #DEFAULT_INHERIT_CLASS_PATH}. 845 * 846 * @return whether the current class path is being inherited or not. 847 */ 848 boolean isInheritClassPath(); 849 850 /** 851 * Set whether the class path is inherited from the active JVM or not. 852 * 853 * <p>Unless otherwise changed or specified, implementations should default to 854 * {@link #DEFAULT_INHERIT_CLASS_PATH}. 855 * 856 * @param inheritClassPath {@code true} to include it, or {@code false} to exclude it. 857 * @return this compiler object for further call chaining. 858 */ 859 JctCompiler inheritClassPath(boolean inheritClassPath); 860 861 /** 862 * Get whether the module path is inherited from the active JVM or not. 863 * 864 * <p>Unless otherwise changed or specified, implementations should default to 865 * {@link #DEFAULT_INHERIT_MODULE_PATH}. 866 * 867 * @return whether the module path is being inherited or not. 868 */ 869 boolean isInheritModulePath(); 870 871 /** 872 * Set whether the module path is inherited from the active JVM or not. 873 * 874 * <p>Unless otherwise changed or specified, implementations should default to 875 * {@link #DEFAULT_INHERIT_MODULE_PATH}. 876 * 877 * @param inheritModulePath {@code true} to include it, or {@code false} to exclude it. 878 * @return this compiler object for further call chaining. 879 */ 880 JctCompiler inheritModulePath(boolean inheritModulePath); 881 882 /** 883 * Get whether the system module path is inherited from the active JVM or not. 884 * 885 * <p>Unless otherwise changed or specified, implementations should default to 886 * {@link #DEFAULT_INHERIT_SYSTEM_MODULE_PATH}. 887 * 888 * @return whether the system module path is being inherited or not. 889 */ 890 boolean isInheritSystemModulePath(); 891 892 /** 893 * Set whether the system module path is inherited from the active JVM or not. 894 * 895 * <p>Unless otherwise changed or specified, implementations should default to 896 * {@link #DEFAULT_INHERIT_SYSTEM_MODULE_PATH}. 897 * 898 * @param inheritSystemModulePath {@code true} to include it, or {@code false} to exclude it. 899 * @return this compiler object for further call chaining. 900 */ 901 JctCompiler inheritSystemModulePath(boolean inheritSystemModulePath); 902 903 /** 904 * Get the output locale. 905 * 906 * <p>Unless otherwise changed or specified, implementations should default to 907 * {@link #DEFAULT_LOCALE}. 908 * 909 * @return the output locale to use. 910 */ 911 Locale getLocale(); 912 913 /** 914 * Set the output locale. 915 * 916 * <p>Unless otherwise changed or specified, implementations should default to 917 * {@link #DEFAULT_LOCALE}. 918 * 919 * @param locale the locale to use. 920 * @return this compiler for further call chaining. 921 */ 922 JctCompiler locale(Locale locale); 923 924 /** 925 * Get the charset being used to write compiler logs with. 926 * 927 * <p>Unless otherwise changed or specified, implementations should default to 928 * {@link #DEFAULT_LOG_CHARSET}. 929 * 930 * @return the charset. 931 */ 932 Charset getLogCharset(); 933 934 /** 935 * Set the charset being used to write compiler logs with. 936 * 937 * <p>Unless otherwise changed or specified, implementations should default to 938 * {@link #DEFAULT_LOG_CHARSET}. 939 * 940 * @param logCharset the charset to use. 941 * @return this compiler for further call chaining. 942 */ 943 JctCompiler logCharset(Charset logCharset); 944 945 /** 946 * Get the current file manager logging mode. 947 * 948 * <p>Unless otherwise changed or specified, implementations should default to 949 * {@link #DEFAULT_FILE_MANAGER_LOGGING_MODE}. 950 * 951 * @return the current file manager logging mode. 952 */ 953 LoggingMode getFileManagerLoggingMode(); 954 955 /** 956 * Set how to handle logging calls to underlying file managers. 957 * 958 * <p>Unless otherwise changed or specified, implementations should default to 959 * {@link #DEFAULT_FILE_MANAGER_LOGGING_MODE}. 960 * 961 * @param fileManagerLoggingMode the mode to use for file manager logging. 962 * @return this compiler for further call chaining. 963 */ 964 JctCompiler fileManagerLoggingMode(LoggingMode fileManagerLoggingMode); 965 966 /** 967 * Get the current diagnostic logging mode. 968 * 969 * <p>Unless otherwise changed or specified, implementations should default to 970 * {@link #DEFAULT_DIAGNOSTIC_LOGGING_MODE}. 971 * 972 * @return the current diagnostic logging mode. 973 */ 974 LoggingMode getDiagnosticLoggingMode(); 975 976 /** 977 * Set how to handle diagnostic capture. 978 * 979 * <p>Unless otherwise changed or specified, implementations should default to 980 * {@link #DEFAULT_DIAGNOSTIC_LOGGING_MODE}. 981 * 982 * @param diagnosticLoggingMode the mode to use for diagnostic capture. 983 * @return this compiler for further call chaining. 984 */ 985 JctCompiler diagnosticLoggingMode(LoggingMode diagnosticLoggingMode); 986 987 /** 988 * Get how to perform annotation processor discovery. 989 * 990 * <p>Unless otherwise changed or specified, implementations should default to 991 * {@link #DEFAULT_ANNOTATION_PROCESSOR_DISCOVERY}. 992 * 993 * <p>Specifying any annotation processors explicitly with 994 * {@link #addAnnotationProcessors(Iterable)} or 995 * {@link #addAnnotationProcessors(Processor...)} will bypass this setting, treating it 996 * as being disabled. 997 * 998 * @return the processor discovery mode to use. 999 */ 1000 AnnotationProcessorDiscovery getAnnotationProcessorDiscovery(); 1001 1002 /** 1003 * Set how to perform annotation processor discovery. 1004 * 1005 * <p>Unless otherwise changed or specified, implementations should default to 1006 * {@link #DEFAULT_ANNOTATION_PROCESSOR_DISCOVERY}. 1007 * 1008 * <p>Specifying any annotation processors explicitly with 1009 * {@link #addAnnotationProcessors(Iterable)} or 1010 * {@link #addAnnotationProcessors(Processor...)} will bypass this setting, treating it 1011 * as being disabled. 1012 * 1013 * @param annotationProcessorDiscovery the processor discovery mode to use. 1014 * @return this compiler for further call chaining. 1015 */ 1016 JctCompiler annotationProcessorDiscovery( 1017 AnnotationProcessorDiscovery annotationProcessorDiscovery); 1018 1019 /** 1020 * Get the debugging info that is enabled. 1021 * 1022 * <p>Unless otherwise changed or specified, implementations should default to 1023 * {@link #DEFAULT_DEBUGGING_INFO}. 1024 * 1025 * @return the set of debugging info flags that are enabled. 1026 * @since 3.0.0 1027 */ 1028 Set<DebuggingInfo> getDebuggingInfo(); 1029 1030 /** 1031 * Set the debugging info level to use. 1032 * 1033 * @param debuggingInfoFlags the set of debugging info flags to enable. 1034 * @return this compiler for further call chaining. 1035 * @since 3.0.0 1036 */ 1037 JctCompiler debuggingInfo(Set<DebuggingInfo> debuggingInfoFlags); 1038 1039 /** 1040 * Determine if including reflective parameter info is enabled or not. 1041 * 1042 * <p>Unless otherwise changed or specified, implementations should default to 1043 * {@link #DEFAULT_PARAMETER_INFO_ENABLED}. 1044 * 1045 * @return the parameter info inclusion preference. 1046 * @since 3.0.0 1047 */ 1048 boolean isParameterInfoEnabled(); 1049 1050 /** 1051 * Set whether to include parameter reflective info by default in compiled classes or not. 1052 * 1053 * @param parameterInfoEnabled whether to include the parameter reflective info or not. 1054 * @return this compiler for further call chaining. 1055 * @since 3.0.0 1056 */ 1057 JctCompiler parameterInfoEnabled(boolean parameterInfoEnabled); 1058}