001/* 002 * Copyright (C) 2022 - 2024, the original author or authors. 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 io.github.ascopes.jct.containers.ModuleContainerGroup; 019import io.github.ascopes.jct.containers.OutputContainerGroup; 020import io.github.ascopes.jct.containers.PackageContainerGroup; 021import io.github.ascopes.jct.diagnostics.TraceDiagnostic; 022import io.github.ascopes.jct.filemanagers.JctFileManager; 023import java.util.List; 024import java.util.Set; 025import javax.tools.JavaFileObject; 026import javax.tools.StandardLocation; 027import org.apiguardian.api.API; 028import org.apiguardian.api.API.Status; 029 030/** 031 * The result of a compilation. 032 * 033 * <p>This provides access to a number of useful pieces of information 034 * including the file manager used for the compilation, compiler logs, 035 * and diagnostics. 036 * 037 * @author Ashley Scopes 038 * @since 0.0.1 039 */ 040@API(since = "0.0.1", status = Status.STABLE) 041public interface JctCompilation { 042 043 /** 044 * Get the command line arguments that were passed to the compiler. 045 * 046 * @return the command line arguments. 047 */ 048 @API(since = "0.5.0", status = Status.STABLE) 049 List<String> getArguments(); 050 051 /** 052 * Determine if warnings were treated as errors. 053 * 054 * @return {@code true} if warnings were treated as errors, or {@code false} otherwise. 055 */ 056 boolean isFailOnWarnings(); 057 058 /** 059 * Determine if the compilation was successful or not. 060 * 061 * @return {@code true} if successful, or {@code false} if not successful. 062 */ 063 boolean isSuccessful(); 064 065 /** 066 * Determine if the compilation was a failure or not. 067 * 068 * @return {@code true} if not successful, or {@code false} if successful. 069 */ 070 default boolean isFailure() { 071 return !isSuccessful(); 072 } 073 074 /** 075 * Get the lines of output produced by the compiler, if any were captured. 076 * 077 * <p>This is separate to diagnostics. 078 * 079 * @return the lines of output. 080 */ 081 List<String> getOutputLines(); 082 083 /** 084 * Get the compilation units used in the compilation. 085 * 086 * @return the compilation units. 087 */ 088 Set<JavaFileObject> getCompilationUnits(); 089 090 /** 091 * Get the diagnostics that were reported by the compilation, in the order that they 092 * were reported. 093 * 094 * @return the diagnostics 095 */ 096 List<TraceDiagnostic<JavaFileObject>> getDiagnostics(); 097 098 /** 099 * Get the file manager that was used to store and manage files. 100 * 101 * <p>This can be used to obtain a classloader for any compiled sources, 102 * which can then be used to reflectively test what the compiler produced. 103 * 104 * @return the file manager. 105 */ 106 JctFileManager getFileManager(); 107 108 /** 109 * Get the output container group for class outputs. 110 * 111 * <p>This usually consists of any {@code *.class} files produced by the compiler, 112 * and is equivalent to {@code target/classes} in a Maven project. 113 * 114 * @return the output container group, or {@code null} if it does not exist. 115 */ 116 default OutputContainerGroup getClassOutputs() { 117 return getFileManager().getOutputContainerGroup(StandardLocation.CLASS_OUTPUT); 118 } 119 120 /** 121 * Get the output container group for source outputs. 122 * 123 * <p>This consists of any generated source code created by annotation processors, 124 * and is equivalent to {@code target/generated-sources} in a Maven project. 125 * 126 * @return the output container group, or {@code null} if it does not exist. 127 */ 128 default OutputContainerGroup getSourceOutputs() { 129 return getFileManager().getOutputContainerGroup(StandardLocation.SOURCE_OUTPUT); 130 } 131 132 /** 133 * Get the package container group for the class path. 134 * 135 * <p>This represents the class path used for compilation. 136 * 137 * @return the package container group, or {@code null} if it does not exist. 138 */ 139 default PackageContainerGroup getClassPath() { 140 return getFileManager().getPackageContainerGroup(StandardLocation.CLASS_PATH); 141 } 142 143 /** 144 * Get the package container group for the source path. 145 * 146 * <p>This is equivalent to {@code src/main/java} and {@code src/main/resources} 147 * in a Maven project. 148 * 149 * @return the package container group, or {@code null} if it does not exist. 150 */ 151 default PackageContainerGroup getSourcePath() { 152 return getFileManager().getPackageContainerGroup(StandardLocation.SOURCE_PATH); 153 } 154 155 /** 156 * Get the package container group for the annotation processor path. 157 * 158 * @return the package container group, or {@code null} if it does not exist. 159 */ 160 default PackageContainerGroup getAnnotationProcessorPath() { 161 return getFileManager().getPackageContainerGroup(StandardLocation.ANNOTATION_PROCESSOR_PATH); 162 } 163 164 /** 165 * Get the module container group for the annotation processor module path. 166 * 167 * @return the module container group, or {@code null} if it does not exist. 168 */ 169 default ModuleContainerGroup getAnnotationProcessorModulePath() { 170 return getFileManager() 171 .getModuleContainerGroup(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH); 172 } 173 174 /** 175 * Get the package container group for the platform class path (a.k.a. the bootstrap class path). 176 * 177 * <p>You generally do not need to use this. The platform class path mechanism has been mostly 178 * replaced by the use of the system modules path as of Java 11. It is simply provided for 179 * backwards compatibility. 180 * 181 * @return the package container group, or {@code null} if it does not exist. 182 */ 183 default PackageContainerGroup getPlatformClassPath() { 184 return getFileManager().getPackageContainerGroup(StandardLocation.PLATFORM_CLASS_PATH); 185 } 186 187 /** 188 * Get the output container group for the native header file outputs. 189 * 190 * <p>If you invoke {@code javac} with the {@code -H} flag, then this represents the 191 * directory that C/C++ header file stubs for JNI are written to. 192 * 193 * @return the output container group, or {@code null} if it does not exist. 194 */ 195 default OutputContainerGroup getNativeHeaderOutputs() { 196 return getFileManager().getOutputContainerGroup(StandardLocation.NATIVE_HEADER_OUTPUT); 197 } 198 199 /** 200 * Get the module container group for the module source path. 201 * 202 * <p>Many build tools do not provide a direct equivalent of this mechanism as of now, but 203 * this is a source path introduced in Java 9 that allows specifying multiple named JPMS 204 * modules to compile under a single compilation invocation. 205 * 206 * <p>For example, you may use this in a project to compile an API module, a default 207 * implementation module, and a module containing unit tests all together. 208 * 209 * @return the module container group, or {@code null} if it does not exist. 210 */ 211 default ModuleContainerGroup getModuleSourcePath() { 212 return getFileManager().getModuleContainerGroup(StandardLocation.MODULE_SOURCE_PATH); 213 } 214 215 /** 216 * Get the module container group for the upgrade module path. 217 * 218 * <p>You generally will not need to use this, as this is a mechanism used to upgrade 219 * modules in-place incrementally with fixes without redistributing the entire application. 220 * 221 * @return the module container group, or {@code null} if it does not exist. 222 */ 223 default ModuleContainerGroup getUpgradeModulePath() { 224 return getFileManager().getModuleContainerGroup(StandardLocation.UPGRADE_MODULE_PATH); 225 } 226 227 /** 228 * Get the module container group for all system modules that are part of the JDK distribution. 229 * 230 * <p>This will usually just point to the Java standard library. 231 * 232 * @return the module container group, or {@code null} if it does not exist. 233 */ 234 default ModuleContainerGroup getSystemModules() { 235 return getFileManager().getModuleContainerGroup(StandardLocation.SYSTEM_MODULES); 236 } 237 238 /** 239 * Get the module container group for the module path. 240 * 241 * <p>This is equivalent to the class path, but holds any JPMS modules. 242 * 243 * @return the module container group, or {@code null} if it does not exist. 244 */ 245 default ModuleContainerGroup getModulePath() { 246 return getFileManager().getModuleContainerGroup(StandardLocation.MODULE_PATH); 247 } 248 249 /** 250 * Get the module container group for the patch module path. 251 * 252 * <p>You generally will not need to use this. It consists of patchable module sources that 253 * can be used to inject additional classes into a module. This can be used for cases like 254 * unit tests where you wish to embed the unit test classes into the existing application 255 * module to exploit features such as package private access. 256 * 257 * @return the module container group, or {@code null} if it does not exist. 258 */ 259 default ModuleContainerGroup getPatchModulePath() { 260 return getFileManager().getModuleContainerGroup(StandardLocation.PATCH_MODULE_PATH); 261 } 262}