001/*
002 * Copyright (C) 2022 - 2023, 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.workspaces;
017
018import io.github.ascopes.jct.filemanagers.JctFileManager;
019import io.github.ascopes.jct.filemanagers.ModuleLocation;
020import java.io.UncheckedIOException;
021import java.nio.file.Path;
022import java.util.List;
023import java.util.Map;
024import javax.tools.JavaFileManager.Location;
025import javax.tools.StandardLocation;
026import org.apiguardian.api.API;
027import org.apiguardian.api.API.Status;
028
029/**
030 * Interface for a Workspace to hold files and directories within.
031 *
032 * <p>This acts as a nexus for managing the lifetime of test sources and directories,
033 * and should be used within a try-with-resources block to ensure temporary files get released after
034 * the test completes.
035 *
036 * <p>While this interface may seem somewhat intimidating due to the number of methods it provides,
037 * you will usually only ever need to use a small subset of them. The main ones you probably will
038 * want to use are:
039 *
040 * <ul>
041 *   <li>
042 *     {@link #addSourcePathPackage(Path)} - for copying a source path tree from your file system.
043 *   </li>
044 *   <li>
045 *     {@link #createSourcePathPackage()} - for creating a new source path tree.
046 *   </li>
047 *   <li>
048 *    {@link #addClassPathPackage(Path)} - for adding a class path resource (usually a JAR or a
049 *    directory of packages of classes).
050 *   </li>
051 *   <li>
052 *    {@link #addModulePathModule(String, Path)} - for adding a module path resource (usually a JAR
053 *    or a directory of packages of classes).
054 *   </li>
055 *   <li>
056 *     {@link #getClassPathPackages()} - for fetching all class path resources.
057 *   </li>
058 *   <li>
059 *     {@link #getModulePathModules()} - for fetching all module path resources.
060 *   </li>
061 *   <li>
062 *     {@link #getSourceOutputPackages()} - for fetching all generated source packages.
063 *   </li>
064 *   <li>
065 *     {@link #getSourceOutputModules()} - for fetching all generated source modules.
066 *   </li>
067 *   <li>
068 *     {@link #close()} - to close any resources in the temporary file system.
069 *   </li>
070 * </ul>
071 *
072 * <p>A simple example of usage of this interface would be the following:
073 *
074 * <pre><code>
075 *   try (Workspace workspace = Workspaces.newWorkspace(PathStrategy.TEMP_DIRECTORIES)) {
076 *     workspace
077 *        .createSourcePathPackage()
078 *        .copyContentsFrom("src", "test", "resources", "test-data");
079 *
080 *     var compilation = someCompiler.compile(workspace);
081 *
082 *     assertThat(compilation).isSuccessful();
083 *   }
084 * </code></pre>
085 *
086 * <p>Remember that files that are created as the result of a compilation can be queried via
087 * {@link JctFileManager}, which is accessible on the {@code compilation} result object. This may
088 * more accurately represent the logical project structure that is the result of various
089 * processing operations during compilation.
090 *
091 * @author Ashley Scopes
092 * @since 0.0.1
093 */
094@API(since = "0.0.1", status = Status.STABLE)
095@SuppressWarnings({"unused", "UnusedReturnValue"})
096public interface Workspace extends AutoCloseable {
097
098  /**
099   * Attempt to close all resources in this workspace.
100   *
101   * @throws UncheckedIOException if an error occurs.
102   */
103  @Override
104  void close();
105
106  /**
107   * Determine if the workspace is closed or not.
108   *
109   * @return {@code true} if closed, {@code false} if open.
110   * @since 0.4.0
111   */
112  @API(since = "0.4.0", status = Status.STABLE)
113  boolean isClosed();
114
115  ///
116  /// Accessor operations
117  ///
118
119  /**
120   * Get an immutable copy of the current paths to operate on.
121   *
122   * @return the paths.
123   */
124  Map<Location, List<? extends PathRoot>> getAllPaths();
125
126  /**
127   * Get the collection of path roots associated with the given module.
128   *
129   * <p>Usually this should only ever contain one path root at a maximum, although
130   * {@link Workspace} does not explicitly enforce this constraint.
131   *
132   * <p>If no results were found, then an empty collection is returned.
133   *
134   * @param location   the module-oriented or output location.
135   * @param moduleName the module name within the location.
136   * @return the collection of paths.
137   * @throws IllegalArgumentException if the location is neither
138   *                                  {@link Location#isModuleOrientedLocation() module-oriented} or
139   *                                  an {@link Location#isOutputLocation() output location}. This
140   *                                  will also be raised if this method is called with an instance
141   *                                  of {@link ModuleLocation} (you should use
142   *                                  {@link #getPackages(Location)} instead for this).
143   * @see #getPackages(Location)
144   * @see #getModules(Location)
145   * @since 0.1.0
146   */
147  List<? extends PathRoot> getModule(Location location, String moduleName);
148
149  /**
150   * Get the collection of modules associated with the given location.
151   *
152   * <p>If no results were found, then an empty map is returned.
153   *
154   * @param location the location to get the modules for.
155   * @return the map of module names to lists of associated paths.
156   * @throws IllegalArgumentException if the location is neither
157   *                                  {@link Location#isModuleOrientedLocation() module-oriented} or
158   *                                  an {@link Location#isOutputLocation() output location}. This
159   *                                  will also be raised if this method is called with an instance
160   *                                  of {@link ModuleLocation}.
161   * @see #getModule(Location, String)
162   * @since 0.1.0
163   */
164  Map<String, List<? extends PathRoot>> getModules(Location location);
165
166  /**
167   * Get the path strategy in use.
168   *
169   * @return the path strategy.
170   */
171  PathStrategy getPathStrategy();
172
173  /**
174   * Get the collection of path roots associated with the given location.
175   *
176   * <p>If no results were found, then an empty collection is returned.
177   *
178   * @param location the location to get.
179   * @return the collection of paths.
180   * @throws IllegalArgumentException if the location is
181   *                                  {@link Location#isModuleOrientedLocation() module-oriented}.
182   * @see #getModule(Location, String)
183   * @since 0.1.0
184   */
185  List<? extends PathRoot> getPackages(Location location);
186
187  ///
188  /// Mutative operations
189  ///
190
191  /**
192   * Add an existing package root to this workspace and associate it with the given location.
193   *
194   * <p>The following constraints must be met, otherwise an {@link IllegalArgumentException}
195   * will be thrown:
196   *
197   * <ul>
198   *   <li>
199   *     The {@code location} must not be
200   *     {@link Location#isModuleOrientedLocation() module-oriented}.
201   *   </li>
202   *   <li>
203   *     The {@code path} must exist.
204   *   </li>
205   * </ul>
206   *
207   * <p>For example, this would add the package tree in {@code src/test/resources/packages}
208   * into the {@link StandardLocation#SOURCE_PATH source code path} that is used to compile files:
209   *
210   * <pre><code>
211   *   var path = Path.of("src", "test", "resources", "packages");
212   *   workspace.addPackage(StandardLocation.SOURCE_PATH, path);
213   * </code></pre>
214   *
215   * @param location the location to associate with.
216   * @param path     the path to add.
217   * @throws IllegalArgumentException if the inputs are invalid.
218   * @see #addModule(Location, String, Path)
219   * @see #createPackage(Location)
220   * @see #createModule(Location, String)
221   */
222  void addPackage(Location location, Path path);
223
224  /**
225   * Add an existing package root to this workspace and associate it with the given module name in
226   * the given location.
227   *
228   * <p>The following constraints must be met, otherwise an {@link IllegalArgumentException}
229   * will be thrown:
230   *
231   * <ul>
232   *   <li>
233   *     The {@code location} must be {@link Location#isModuleOrientedLocation() module-oriented}
234   *     or an {@link Location#isOutputLocation() output location}.
235   *   </li>
236   *   <li>
237   *     The {@code location} must not be a {@link ModuleLocation module-location handle} already.
238   *   </li>
239   *   <li>
240   *     The {@code path} must exist.
241   *   </li>
242   * </ul>
243   *
244   * <p>For example, this would add the package tree in {@code src/test/resources/packages}
245   * into the {@link StandardLocation#MODULE_SOURCE_PATH module source code path} under the module
246   * name {@code foo.bar}:
247   *
248   * <pre><code>
249   *   var path = Path.of("src", "test", "resources", "packages");
250   *   workspace.addModule(StandardLocation.MODULE_SOURCE_PATH, "foo.bar", path);
251   * </code></pre>
252   *
253   * @param location   the location to associate with.
254   * @param moduleName the name of the module.
255   * @param path       the path to add.
256   * @throws IllegalArgumentException if the inputs are invalid.
257   * @see #addPackage(Location, Path)
258   * @see #createPackage(Location)
259   * @see #createModule(Location, String)
260   */
261  void addModule(Location location, String moduleName, Path path);
262
263  /**
264   * Create a new test directory for a package root and associate it with the given location.
265   *
266   * <p>This path will be destroyed when the workspace is {@link #close() closed}.
267   *
268   * <p>The following constraints must be met, otherwise an {@link IllegalArgumentException}
269   * will be thrown:
270   *
271   * <ul>
272   *   <li>
273   *     The {@code location} must not be
274   *     {@link Location#isModuleOrientedLocation() module-oriented}.
275   *   </li>
276   * </ul>
277   *
278   * <p>For example, this would create a new source root that you could add files to:
279   *
280   * <pre><code>
281   *   workspace.createPackage(StandardLocation.SOURCE_PATH);
282   * </code></pre>
283   *
284   * @param location the location to associate with.
285   * @return the test directory that was created.
286   * @throws IllegalArgumentException if the inputs are invalid.
287   * @see #createModule(Location, String)
288   * @see #addPackage(Location, Path)
289   * @see #addModule(Location, String, Path)
290   */
291  ManagedDirectory createPackage(Location location);
292
293  /**
294   * Create a new test directory for a package root and associate it with the given module name in
295   * the given location.
296   *
297   * <p>This path will be destroyed when the workspace is {@link #close() closed}.
298   *
299   * <p>The following constraints must be met, otherwise an {@link IllegalArgumentException}
300   * will be thrown:
301   *
302   * <ul>
303   *   <li>
304   *     The {@code location} must be {@link Location#isModuleOrientedLocation() module-oriented}
305   *     or an {@link Location#isOutputLocation() output location}.
306   *   </li>
307   *   <li>
308   *     The {@code location} must not be a {@link ModuleLocation module-location handle} already.
309   *   </li>
310   * </ul>
311   *
312   * <p>For example, this would create a new multi-module source root that you could add files to,
313   * for a module named {@code foo.bar}:
314   *
315   * <pre><code>
316   *   workspace.createModule(StandardLocation.MODULE_SOURCE_PATH, "foo.bar");
317   * </code></pre>
318   *
319   * @param location   the location to associate with.
320   * @param moduleName the module name to use.
321   * @return the test directory that was created.
322   * @throws IllegalArgumentException if the inputs are invalid.
323   * @see #createPackage(Location)
324   * @see #addPackage(Location, Path)
325   * @see #addModule(Location, String, Path)
326   */
327  ManagedDirectory createModule(Location location, String moduleName);
328
329  ///
330  /// Default implementation helpers.
331  ///
332
333  /**
334   * Add a package to the {@link StandardLocation#CLASS_OUTPUT class outputs}.
335   *
336   * @param path the path to add.
337   * @throws IllegalArgumentException if the path does not exist.
338   * @see #addPackage(Location, Path)
339   * @see #addClassOutputModule(String, Path)
340   * @see #createClassOutputPackage()
341   * @see #createClassOutputModule(String)
342   */
343  default void addClassOutputPackage(Path path) {
344    addPackage(StandardLocation.CLASS_OUTPUT, path);
345  }
346
347  /**
348   * Add a module to the {@link StandardLocation#CLASS_OUTPUT class outputs}.
349   *
350   * @param moduleName the module name.
351   * @param path       the path to add.
352   * @throws IllegalArgumentException if the path does not exist.
353   * @see #addModule(Location, String, Path)
354   * @see #addClassOutputPackage(Path)
355   * @see #createClassOutputPackage()
356   * @see #createClassOutputModule(String)
357   */
358  default void addClassOutputModule(String moduleName, Path path) {
359    addModule(StandardLocation.CLASS_OUTPUT, moduleName, path);
360  }
361
362  /**
363   * Add a package to the {@link StandardLocation#SOURCE_OUTPUT generated source outputs}.
364   *
365   * @param path the path to add.
366   * @throws IllegalArgumentException if the path does not exist.
367   * @see #addPackage(Location, Path)
368   * @see #addSourceOutputModule(String, Path)
369   * @see #createSourceOutputPackage()
370   * @see #createSourceOutputModule(String)
371   */
372  default void addSourceOutputPackage(Path path) {
373    addPackage(StandardLocation.SOURCE_OUTPUT, path);
374  }
375
376  /**
377   * Add a module to the {@link StandardLocation#SOURCE_OUTPUT generated source outputs}.
378   *
379   * @param moduleName the module name.
380   * @param path       the path to add.
381   * @throws IllegalArgumentException if the path does not exist.
382   * @see #addModule(Location, String, Path)
383   * @see #addSourceOutputPackage(Path)
384   * @see #createSourceOutputPackage()
385   * @see #createSourceOutputModule(String)
386   */
387  default void addSourceOutputModule(String moduleName, Path path) {
388    addModule(StandardLocation.SOURCE_OUTPUT, moduleName, path);
389  }
390
391  /**
392   * Add a package to the {@link StandardLocation#CLASS_PATH class path}.
393   *
394   * <p>If you are adding JPMS modules, you may want to use
395   * {@link #addModulePathModule(String, Path)} instead.
396   *
397   * @param path the path to add.
398   * @throws IllegalArgumentException if the path does not exist.
399   * @see #addPackage(Location, Path)
400   * @see #addModulePathModule(String, Path)
401   * @see #createClassPathPackage()
402   * @see #createModulePathModule(String)
403   */
404  default void addClassPathPackage(Path path) {
405    addPackage(StandardLocation.CLASS_PATH, path);
406  }
407
408  /**
409   * Add a module to the {@link StandardLocation#MODULE_PATH module path}.
410   *
411   * <p>If you are adding non-JPMS modules, you may want to use
412   * {@link #addClassPathPackage(Path)} instead.
413   *
414   * @param moduleName the module name.
415   * @param path       the path to add.
416   * @throws IllegalArgumentException if the path does not exist.
417   * @see #addModule(Location, String, Path)
418   * @see #addClassPathPackage(Path)
419   * @see #createClassPathPackage()
420   * @see #createModulePathModule(String)
421   */
422  default void addModulePathModule(String moduleName, Path path) {
423    addModule(StandardLocation.MODULE_PATH, moduleName, path);
424  }
425
426  /**
427   * Add a package to the {@link StandardLocation#SOURCE_PATH legacy source path}.
428   *
429   * <p>This is the location you will usually tend to use for your source code.
430   *
431   * <p>If you wish to define multiple JPMS modules in your source code tree to compile together,
432   * you will want to consider using {@link #addSourcePathModule(String, Path)} instead. For most
433   * purposes, however, this method is the one you will want to be using if your code is not in a
434   * <strong>named</strong> module directory (so not something like
435   * {@code src/my.module/org/example/...}).
436   *
437   * @param path the path to add.
438   * @throws IllegalArgumentException if the path does not exist.
439   * @see #addPackage(Location, Path)
440   * @see #addSourcePathModule(String, Path)
441   * @see #createSourcePathPackage()
442   * @see #createSourcePathModule(String)
443   */
444  default void addSourcePathPackage(Path path) {
445    addPackage(StandardLocation.SOURCE_PATH, path);
446  }
447
448  /**
449   * Add a module to the {@link StandardLocation#MODULE_SOURCE_PATH module source path}.
450   *
451   * <p>Note that this will signal to the compiler to run in multi-module compilation mode.
452   * Any source packages that were {@link #addSourcePathPackage(Path) added} or
453   * {@link #createSourcePathPackage() created} will be ignored.
454   *
455   * <p>If you are using a single-module, you can
456   * {@link #addSourcePathPackage(Path) add a source package} and include a {@code module-info.java}
457   * in the base directory instead.
458   *
459   * @param moduleName the module name.
460   * @param path       the path to add.
461   * @throws IllegalArgumentException if the path does not exist.
462   * @see #addModule(Location, String, Path)
463   * @see #addSourcePathPackage(Path)
464   * @see #createSourcePathPackage()
465   * @see #createSourcePathModule(String)
466   */
467  default void addSourcePathModule(String moduleName, Path path) {
468    addModule(StandardLocation.MODULE_SOURCE_PATH, moduleName, path);
469  }
470
471  /**
472   * Add a package to the
473   * {@link StandardLocation#ANNOTATION_PROCESSOR_PATH annotation processor path}.
474   *
475   * <p>Note that this will be ignored if the compiler is provided with explicit annotation
476   * processor instances to run.
477   *
478   * @param path the path to add.
479   * @throws IllegalArgumentException if the path does not exist.
480   * @see #addPackage(Location, Path)
481   * @see #addAnnotationProcessorPathModule(String, Path)
482   * @see #createAnnotationProcessorPathPackage()
483   * @see #createAnnotationProcessorPathModule(String)
484   */
485  default void addAnnotationProcessorPathPackage(Path path) {
486    addPackage(StandardLocation.ANNOTATION_PROCESSOR_PATH, path);
487  }
488
489  /**
490   * Add a module to the
491   * {@link StandardLocation#ANNOTATION_PROCESSOR_MODULE_PATH annotation processor module path}.
492   *
493   * <p>Note that this will be ignored if the compiler is provided with explicit annotation
494   * processor instances to run.
495   *
496   * @param moduleName the module name.
497   * @param path       the path to add.
498   * @throws IllegalArgumentException if the path does not exist.
499   * @see #addModule(Location, String, Path)
500   * @see #addAnnotationProcessorPathPackage(Path)
501   * @see #createAnnotationProcessorPathPackage()
502   * @see #createAnnotationProcessorPathModule
503   */
504  default void addAnnotationProcessorPathModule(String moduleName, Path path) {
505    addModule(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, moduleName, path);
506  }
507
508  /**
509   * Add a package to the {@link StandardLocation#PLATFORM_CLASS_PATH platform class path} (also
510   * known as the boot class path).
511   *
512   * @param path the path to add.
513   * @throws IllegalArgumentException if the path does not exist.
514   * @see #addPackage(Location, Path)
515   * @see #createPlatformClassPathPackage()
516   * @deprecated The platform class path has been mostly replaced by the use of system modules, so
517   * should not be used. This will be removed in v1.0.0.
518   */
519  @Deprecated(forRemoval = true, since = "0.6.0")
520  @SuppressWarnings("DeprecatedIsStillUsed")
521  default void addPlatformClassPathPackage(Path path) {
522    addPackage(StandardLocation.PLATFORM_CLASS_PATH, path);
523  }
524
525  /**
526   * Add a package to the {@link StandardLocation#NATIVE_HEADER_OUTPUT native header outputs}.
527   *
528   * @param path the path to add.
529   * @throws IllegalArgumentException if the path does not exist.
530   * @see #addPackage(Location, Path)
531   * @see #addNativeHeaderOutputModule(String, Path)
532   * @see #createNativeHeaderOutputPackage()
533   * @see #createNativeHeaderOutputModule(String)
534   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
535   * this is being removed. You should instead call {@link #addPackage(Location, Path)}, passing
536   * {@link StandardLocation#NATIVE_HEADER_OUTPUT} as the first parameter.
537   */
538  @Deprecated(forRemoval = true, since = "0.6.0")
539  @SuppressWarnings("DeprecatedIsStillUsed")
540  default void addNativeHeaderOutputPackage(Path path) {
541    addPackage(StandardLocation.NATIVE_HEADER_OUTPUT, path);
542  }
543
544  /**
545   * Add a module to the {@link StandardLocation#NATIVE_HEADER_OUTPUT native header outputs}.
546   *
547   * @param moduleName the name of the module.
548   * @param path       the path to add.
549   * @throws IllegalArgumentException if the path does not exist.
550   * @see #addPackage(Location, Path)
551   * @see #addNativeHeaderOutputPackage(Path)
552   * @see #createNativeHeaderOutputPackage()
553   * @see #createNativeHeaderOutputModule(String)
554   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
555   * this is being removed. You should instead call {@link #addModule(Location, String, Path)},
556   * passing {@link StandardLocation#NATIVE_HEADER_OUTPUT} as the first parameter.
557   */
558  @Deprecated(forRemoval = true, since = "0.6.0")
559  @SuppressWarnings("DeprecatedIsStillUsed")
560  default void addNativeHeaderOutputModule(String moduleName, Path path) {
561    addModule(StandardLocation.NATIVE_HEADER_OUTPUT, moduleName, path);
562  }
563
564  /**
565   * Add a module to the {@link StandardLocation#UPGRADE_MODULE_PATH upgrade module path}.
566   *
567   * @param moduleName the module name.
568   * @param path       the path to add.
569   * @throws IllegalArgumentException if the path does not exist.
570   * @see #addModule(Location, String, Path)
571   * @see #createUpgradeModulePathModule(String)
572   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
573   * this is being removed. You should instead call {@link #addModule(Location, String, Path)},
574   * passing {@link StandardLocation#UPGRADE_MODULE_PATH} as the first parameter.
575   */
576  @Deprecated(forRemoval = true, since = "0.6.0")
577  @SuppressWarnings("DeprecatedIsStillUsed")
578  default void addUpgradeModulePathModule(String moduleName, Path path) {
579    addModule(StandardLocation.UPGRADE_MODULE_PATH, moduleName, path);
580  }
581
582  /**
583   * Add a module to the {@link StandardLocation#SYSTEM_MODULES system module path}.
584   *
585   * @param moduleName the module name.
586   * @param path       the path to add.
587   * @throws IllegalArgumentException if the path does not exist.
588   * @see #addModule(Location, String, Path)
589   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
590   * this is being removed. You should instead call {@link #addModule(Location, String, Path)},
591   * passing {@link StandardLocation#SYSTEM_MODULES} as the first parameter.
592   */
593  @Deprecated(forRemoval = true, since = "0.6.0")
594  @SuppressWarnings("DeprecatedIsStillUsed")
595  default void addSystemModulePathModule(String moduleName, Path path) {
596    addModule(StandardLocation.SYSTEM_MODULES, moduleName, path);
597  }
598
599  /**
600   * Add a module to the {@link StandardLocation#PATCH_MODULE_PATH patch module path}.
601   *
602   * @param moduleName the module name.
603   * @param path       the path to add.
604   * @throws IllegalArgumentException if the path does not exist.
605   * @see #addModule(Location, String, Path)
606   * @see #createPatchModulePathModule(String)
607   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
608   * this is being removed. You should instead call {@link #addModule(Location, String, Path)},
609   * passing {@link StandardLocation#PATCH_MODULE_PATH} as the first parameter.
610   */
611  @Deprecated(forRemoval = true, since = "0.6.0")
612  @SuppressWarnings("DeprecatedIsStillUsed")
613  default void addPatchModulePathModule(String moduleName, Path path) {
614    addModule(StandardLocation.PATCH_MODULE_PATH, moduleName, path);
615  }
616
617  /**
618   * Create a package in the {@link StandardLocation#CLASS_OUTPUT class outputs}.
619   *
620   * @return the created test directory.
621   * @see #createPackage(Location)
622   * @see #createClassOutputModule(String)
623   * @see #addClassOutputPackage(Path)
624   * @see #addClassOutputModule(String, Path)
625   */
626  default ManagedDirectory createClassOutputPackage() {
627    return createPackage(StandardLocation.CLASS_OUTPUT);
628  }
629
630  /**
631   * Create a module in the {@link StandardLocation#CLASS_OUTPUT class outputs}.
632   *
633   * @param moduleName the module name.
634   * @return the created test directory.
635   * @see #createModule(Location, String)
636   * @see #createClassOutputPackage()
637   * @see #addClassOutputPackage(Path)
638   * @see #addClassOutputModule(String, Path)
639   */
640  default ManagedDirectory createClassOutputModule(String moduleName) {
641    return createModule(StandardLocation.CLASS_OUTPUT, moduleName);
642  }
643
644  /**
645   * Create a package in the {@link StandardLocation#SOURCE_OUTPUT generated source outputs}.
646   *
647   * @return the created test directory.
648   * @see #createPackage(Location)
649   * @see #createSourceOutputModule(String)
650   * @see #addSourceOutputPackage(Path)
651   * @see #addSourceOutputModule(String, Path)
652   */
653  default ManagedDirectory createSourceOutputPackage() {
654    return createPackage(StandardLocation.SOURCE_OUTPUT);
655  }
656
657  /**
658   * Create a module in the {@link StandardLocation#SOURCE_OUTPUT generated source outputs}.
659   *
660   * @param moduleName the module name.
661   * @return the created test directory.
662   * @see #createModule(Location, String)
663   * @see #createSourceOutputPackage()
664   * @see #addSourceOutputPackage(Path)
665   * @see #addSourceOutputModule(String, Path)
666   */
667  default ManagedDirectory createSourceOutputModule(String moduleName) {
668    return createModule(StandardLocation.SOURCE_OUTPUT, moduleName);
669  }
670
671  /**
672   * Create a package in the {@link StandardLocation#CLASS_PATH class path}.
673   *
674   * <p>If you are adding JPMS modules, you may want to use
675   * {@link #createModulePathModule(String)} instead.
676   *
677   * @return the created test directory.
678   * @see #createPackage(Location)
679   * @see #createModulePathModule(String)
680   * @see #addClassPathPackage(Path)
681   * @see #addModulePathModule(String, Path)
682   */
683  default ManagedDirectory createClassPathPackage() {
684    return createPackage(StandardLocation.CLASS_PATH);
685  }
686
687  /**
688   * Create a module in the {@link StandardLocation#MODULE_PATH module path}.
689   *
690   * <p>If you are adding non-JPMS modules, you may want to use
691   * {@link #createClassPathPackage()} instead.
692   *
693   * @param moduleName the module name.
694   * @return the created test directory.
695   * @see #createModule(Location, String)
696   * @see #createClassPathPackage()
697   * @see #addModulePathModule(String, Path)
698   * @see #addClassPathPackage(Path)
699   */
700  default ManagedDirectory createModulePathModule(String moduleName) {
701    return createModule(StandardLocation.MODULE_PATH, moduleName);
702  }
703
704  /**
705   * Create a package in the {@link StandardLocation#SOURCE_PATH source path}.
706   *
707   * <p>If you wish to define multiple JPMS modules in your source code tree to compile together,
708   * you will want to consider using {@link #createSourcePathModule(String)} instead. For most
709   * purposes, however, this method is the one you will want to be using if your code is not in a
710   * <strong>named</strong> module directory (so not something like
711   * {@code src/my.module/org/example/...}).
712   *
713   * @return the created test directory.
714   * @see #createPackage(Location)
715   * @see #createSourcePathModule(String)
716   * @see #addSourcePathPackage(Path)
717   * @see #addSourcePathModule(String, Path)
718   */
719  default ManagedDirectory createSourcePathPackage() {
720    return createPackage(StandardLocation.SOURCE_PATH);
721  }
722
723  /**
724   * Create a module in the {@link StandardLocation#MODULE_SOURCE_PATH module source path}.
725   *
726   * <p>Note that this will signal to the compiler to run in multi-module compilation mode.
727   * Any source packages that were {@link #createSourcePathPackage() created} or
728   * {@link #addSourcePathPackage(Path) added} will be ignored.
729   *
730   * <p>If you are using a single-module, you can
731   * {@link #createSourcePathPackage() create a source package} and include a
732   * {@code module-info.java} in the base directory instead.
733   *
734   * @param moduleName the module name.
735   * @return the created test directory.
736   * @see #createModule(Location, String)
737   * @see #createSourcePathPackage()
738   * @see #addSourcePathPackage(Path)
739   * @see #addSourcePathModule(String, Path)
740   */
741  default ManagedDirectory createSourcePathModule(String moduleName) {
742    return createModule(StandardLocation.MODULE_SOURCE_PATH, moduleName);
743  }
744
745  /**
746   * Create a package in the
747   * {@link StandardLocation#ANNOTATION_PROCESSOR_PATH annotation processor path}.
748   *
749   * <p>Note that this will be ignored if the compiler is provided with explicit annotation
750   * processor instances to run.
751   *
752   * @return the created test directory.
753   * @see #createPackage(Location)
754   * @see #createAnnotationProcessorPathModule(String)
755   * @see #addAnnotationProcessorPathPackage(Path)
756   * @see #addAnnotationProcessorPathModule(String, Path)
757   */
758  default ManagedDirectory createAnnotationProcessorPathPackage() {
759    return createPackage(StandardLocation.ANNOTATION_PROCESSOR_PATH);
760  }
761
762  /**
763   * Create a module in the
764   * {@link StandardLocation#ANNOTATION_PROCESSOR_MODULE_PATH annotation processor module path}.
765   *
766   * <p>Note that this will be ignored if the compiler is provided with explicit annotation
767   * processor instances to run.
768   *
769   * @param moduleName the module name.
770   * @return the created test directory.
771   * @see #createModule(Location, String)
772   * @see #createAnnotationProcessorPathPackage()
773   * @see #addAnnotationProcessorPathPackage(Path)
774   * @see #addAnnotationProcessorPathModule(String, Path)
775   */
776  default ManagedDirectory createAnnotationProcessorPathModule(String moduleName) {
777    return createModule(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, moduleName);
778  }
779
780  /**
781   * Create a package in the {@link StandardLocation#PLATFORM_CLASS_PATH platform class path} (also
782   * known as the boot class path).
783   *
784   * @return the created test directory.
785   * @see #createPackage(Location)
786   * @see #addPlatformClassPathPackage(Path)
787   * @deprecated The platform class path has been mostly replaced by the use of system modules, so
788   * should not be used. This will be removed in v1.0.0.
789   */
790  @Deprecated(forRemoval = true, since = "0.6.0")
791  @SuppressWarnings("DeprecatedIsStillUsed")
792  default ManagedDirectory createPlatformClassPathPackage() {
793    return createPackage(StandardLocation.PLATFORM_CLASS_PATH);
794  }
795
796  /**
797   * Create a package in the {@link StandardLocation#NATIVE_HEADER_OUTPUT native header outputs}.
798   *
799   * @return the created test directory.
800   * @see #createPackage(Location)
801   * @see #createNativeHeaderOutputModule(String)
802   * @see #addNativeHeaderOutputPackage(Path)
803   * @see #addNativeHeaderOutputModule(String, Path)
804   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
805   * this is being removed. You should instead call {@link #createPackage(Location)}, passing
806   * {@link StandardLocation#NATIVE_HEADER_OUTPUT} as the first parameter.
807   */
808  @Deprecated(forRemoval = true, since = "0.6.0")
809  @SuppressWarnings("DeprecatedIsStillUsed")
810  default ManagedDirectory createNativeHeaderOutputPackage() {
811    return createPackage(StandardLocation.NATIVE_HEADER_OUTPUT);
812  }
813
814  /**
815   * Create a module in the {@link StandardLocation#NATIVE_HEADER_OUTPUT native header outputs}.
816   *
817   * @param moduleName the module name.
818   * @return the created test directory.
819   * @see #createModule(Location, String)
820   * @see #createNativeHeaderOutputPackage()
821   * @see #addNativeHeaderOutputPackage(Path)
822   * @see #addNativeHeaderOutputModule(String, Path)
823   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
824   * this is being removed. You should instead call {@link #createModule(Location, String)}, passing
825   * {@link StandardLocation#NATIVE_HEADER_OUTPUT} as the first parameter.
826   */
827  @Deprecated(forRemoval = true, since = "0.6.0")
828  @SuppressWarnings("DeprecatedIsStillUsed")
829  default ManagedDirectory createNativeHeaderOutputModule(String moduleName) {
830    return createModule(StandardLocation.NATIVE_HEADER_OUTPUT, moduleName);
831  }
832
833  /**
834   * Create a module in the {@link StandardLocation#UPGRADE_MODULE_PATH upgrade module path}.
835   *
836   * @param moduleName the module name.
837   * @return the created test directory.
838   * @see #createModule(Location, String)
839   * @see #addUpgradeModulePathModule(String, Path)
840   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
841   * this is being removed. You should instead call {@link #createModule(Location, String)},
842   * passing {@link StandardLocation#UPGRADE_MODULE_PATH} as the first parameter.
843   */
844  @Deprecated(forRemoval = true, since = "0.6.0")
845  @SuppressWarnings("DeprecatedIsStillUsed")
846  default ManagedDirectory createUpgradeModulePathModule(String moduleName) {
847    return createModule(StandardLocation.UPGRADE_MODULE_PATH, moduleName);
848  }
849
850  /**
851   * Create a module in the {@link StandardLocation#SYSTEM_MODULES system module path}.
852   *
853   * @param moduleName the module name.
854   * @return the created test directory.
855   * @see #createModule(Location, String)
856   * @see #addSystemModulePathModule(String, Path)
857   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
858   * this is being removed. You should instead call {@link #createModule(Location, String)}, passing
859   * {@link StandardLocation#SYSTEM_MODULES} as the first parameter.
860   */
861  @Deprecated(forRemoval = true, since = "0.6.0")
862  @SuppressWarnings("DeprecatedIsStillUsed")
863  default ManagedDirectory createSystemModulePathModule(String moduleName) {
864    return createModule(StandardLocation.SYSTEM_MODULES, moduleName);
865  }
866
867  /**
868   * Create a module in the {@link StandardLocation#PATCH_MODULE_PATH patch module path}.
869   *
870   * @param moduleName the module name.
871   * @return the created test directory.
872   * @see #createModule(Location, String)
873   * @see #createPatchModulePathModule(String)
874   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
875   * this is being removed. You should instead call {@link #createModule(Location, String)}, passing
876   * {@link StandardLocation#PATCH_MODULE_PATH} as the first parameter.
877   */
878  @Deprecated(forRemoval = true, since = "0.6.0")
879  @SuppressWarnings("DeprecatedIsStillUsed")
880  default ManagedDirectory createPatchModulePathModule(String moduleName) {
881    return createModule(StandardLocation.PATCH_MODULE_PATH, moduleName);
882  }
883
884  /**
885   * Get the non-module path roots for {@link StandardLocation#CLASS_OUTPUT class outputs}.
886   *
887   * @return the roots in a collection, or an empty collection if none were found.
888   * @since 0.1.0
889   */
890  default List<? extends PathRoot> getClassOutputPackages() {
891    return getPackages(StandardLocation.CLASS_OUTPUT);
892  }
893
894  /**
895   * Get the module path roots for {@link StandardLocation#CLASS_OUTPUT class outputs} for the given
896   * module name.
897   *
898   * @param moduleName the module name.
899   * @return the roots in a collection, or an empty collection if none were found.
900   * @since 0.1.0
901   */
902  default List<? extends PathRoot> getClassOutputModule(String moduleName) {
903    return getModule(StandardLocation.CLASS_OUTPUT, moduleName);
904  }
905
906  /**
907   * Get the module path roots for {@link StandardLocation#CLASS_OUTPUT class outputs}.
908   *
909   * @return the roots in a map of module names to lists of roots, or an empty map if none were
910   * found.
911   * @since 0.1.0
912   */
913  default Map<String, List<? extends PathRoot>> getClassOutputModules() {
914    return getModules(StandardLocation.CLASS_OUTPUT);
915  }
916
917  /**
918   * Get the non-module path roots for {@link StandardLocation#SOURCE_OUTPUT source outputs}.
919   *
920   * @return the roots in a collection, or an empty collection if none were found.
921   * @since 0.1.0
922   */
923  default List<? extends PathRoot> getSourceOutputPackages() {
924    return getPackages(StandardLocation.SOURCE_OUTPUT);
925  }
926
927  /**
928   * Get the module path roots for {@link StandardLocation#SOURCE_OUTPUT source outputs} for the
929   * given module name.
930   *
931   * @param moduleName the module name.
932   * @return the roots in a collection, or an empty collection if none were found.
933   * @since 0.1.0
934   */
935  default List<? extends PathRoot> getSourceOutputModule(String moduleName) {
936    return getModule(StandardLocation.SOURCE_OUTPUT, moduleName);
937  }
938
939
940  /**
941   * Get the module path roots for {@link StandardLocation#SOURCE_OUTPUT source outputs}.
942   *
943   * @return the roots in a map of module names to lists of roots, or an empty map if none were
944   * found.
945   * @since 0.1.0
946   */
947  default Map<String, List<? extends PathRoot>> getSourceOutputModules() {
948    return getModules(StandardLocation.SOURCE_OUTPUT);
949  }
950
951  /**
952   * Get the path roots for the {@link StandardLocation#CLASS_PATH class path}.
953   *
954   * @return the roots in a collection, or an empty collection if none were found.
955   * @since 0.1.0
956   */
957  default List<? extends PathRoot> getClassPathPackages() {
958    return getPackages(StandardLocation.CLASS_PATH);
959  }
960
961  /**
962   * Get the path roots for the {@link StandardLocation#SOURCE_PATH source path}.
963   *
964   * @return the roots in a collection, or an empty collection if none were found.
965   * @since 0.1.0
966   */
967  default List<? extends PathRoot> getSourcePathPackages() {
968    return getPackages(StandardLocation.SOURCE_PATH);
969  }
970
971  /**
972   * Get the path roots for the
973   * {@link StandardLocation#ANNOTATION_PROCESSOR_PATH annotation processor path}.
974   *
975   * @return the roots in a collection, or an empty collection if none were found.
976   * @since 0.1.0
977   */
978  default List<? extends PathRoot> getAnnotationProcessorPathPackages() {
979    return getPackages(StandardLocation.ANNOTATION_PROCESSOR_PATH);
980  }
981
982  /**
983   * Get the path roots for the
984   * {@link StandardLocation#ANNOTATION_PROCESSOR_MODULE_PATH annotation processor module path}.
985   *
986   * @param moduleName the module name to get.
987   * @return the roots in a collection, or an empty collection if none were found.
988   * @since 0.1.0
989   */
990  default List<? extends PathRoot> getAnnotationProcessorPathModule(String moduleName) {
991    return getModule(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH, moduleName);
992  }
993
994  /**
995   * Get the module path roots for the
996   * {@link StandardLocation#ANNOTATION_PROCESSOR_MODULE_PATH annotation processor module path}.
997   *
998   * @return the roots in a map of module names to lists of roots, or an empty map if none were
999   * found.
1000   * @since 0.1.0
1001   */
1002  default Map<String, List<? extends PathRoot>> getAnnotationProcessorPathModules() {
1003    return getModules(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH);
1004  }
1005
1006  /**
1007   * Get the path roots for the {@link StandardLocation#PLATFORM_CLASS_PATH platform class path}
1008   * (also known as the boot class path).
1009   *
1010   * @return the roots in a collection, or an empty collection if none were found.
1011   * @since 0.1.0
1012   * @deprecated The platform class path has been mostly replaced by the use of system modules, so
1013   * should not be used. This will be removed in v1.0.0.
1014   */
1015  @Deprecated(forRemoval = true, since = "0.6.0")
1016  @SuppressWarnings("DeprecatedIsStillUsed")
1017  default List<? extends PathRoot> getPlatformClassPathPackages() {
1018    return getPackages(StandardLocation.PLATFORM_CLASS_PATH);
1019  }
1020
1021  /**
1022   * Get the non-module path roots for
1023   * {@link StandardLocation#NATIVE_HEADER_OUTPUT native header outputs}.
1024   *
1025   * @return the roots in a collection, or an empty collection if none were found.
1026   * @since 0.1.0
1027   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1028   * this is being removed. You should instead call {@link #getPackages(Location)}, passing
1029   * {@link StandardLocation#NATIVE_HEADER_OUTPUT} as the first parameter.
1030   */
1031  @Deprecated(forRemoval = true, since = "0.6.0")
1032  @SuppressWarnings("DeprecatedIsStillUsed")
1033  default List<? extends PathRoot> getNativeHeaderOutputPackages() {
1034    return getPackages(StandardLocation.NATIVE_HEADER_OUTPUT);
1035  }
1036
1037  /**
1038   * Get the module path roots for
1039   * {@link StandardLocation#NATIVE_HEADER_OUTPUT native header outputs} for the given module name.
1040   *
1041   * @param moduleName the module name.
1042   * @return the roots in a collection, or an empty collection if none were found.
1043   * @since 0.1.0
1044   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1045   * this is being removed. You should instead call {@link #getModule(Location, String)}, passing
1046   * {@link StandardLocation#NATIVE_HEADER_OUTPUT} as the first parameter.
1047   */
1048  @Deprecated(forRemoval = true, since = "0.6.0")
1049  @SuppressWarnings("DeprecatedIsStillUsed")
1050  default List<? extends PathRoot> getNativeHeaderOutputModule(String moduleName) {
1051    return getModule(StandardLocation.NATIVE_HEADER_OUTPUT, moduleName);
1052  }
1053
1054  /**
1055   * Get the module path roots for
1056   * {@link StandardLocation#NATIVE_HEADER_OUTPUT native header outputs}.
1057   *
1058   * @return the roots in a map of module names to lists of roots, or an empty map if none were
1059   * found.
1060   * @since 0.1.0
1061   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1062   * this is being removed. You should instead call {@link #getModules(Location)}, passing
1063   * {@link StandardLocation#NATIVE_HEADER_OUTPUT} as the first parameter.
1064   */
1065  @Deprecated(forRemoval = true, since = "0.6.0")
1066  @SuppressWarnings("DeprecatedIsStillUsed")
1067  default Map<String, List<? extends PathRoot>> getNativeHeaderOutputModules() {
1068    return getModules(StandardLocation.NATIVE_HEADER_OUTPUT);
1069  }
1070
1071  /**
1072   * Get the path roots for the {@link StandardLocation#MODULE_SOURCE_PATH module source path}.
1073   *
1074   * @param moduleName the module name to get.
1075   * @return the roots in a collection, or an empty collection if none were found.
1076   * @since 0.1.0
1077   */
1078  default List<? extends PathRoot> getSourcePathModule(String moduleName) {
1079    return getModule(StandardLocation.MODULE_SOURCE_PATH, moduleName);
1080  }
1081
1082  /**
1083   * Get the module path roots for the
1084   * {@link StandardLocation#MODULE_SOURCE_PATH module source paths}.
1085   *
1086   * @return the roots in a map of module names to lists of roots, or an empty map if none were
1087   * found.
1088   * @since 0.1.0
1089   */
1090  default Map<String, List<? extends PathRoot>> getSourcePathModules() {
1091    return getModules(StandardLocation.MODULE_SOURCE_PATH);
1092  }
1093
1094  /**
1095   * Get the path roots for the {@link StandardLocation#UPGRADE_MODULE_PATH upgrade module path}.
1096   *
1097   * @param moduleName the module name to get.
1098   * @return the roots in a collection, or an empty collection if none were found.
1099   * @since 0.1.0
1100   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1101   * this is being removed. You should instead call {@link #getModule(Location, String)}, passing
1102   * {@link StandardLocation#UPGRADE_MODULE_PATH} as the first parameter.
1103   */
1104  @Deprecated(forRemoval = true, since = "0.6.0")
1105  @SuppressWarnings("DeprecatedIsStillUsed")
1106  default List<? extends PathRoot> getUpgradeModulePathModule(String moduleName) {
1107    return getModule(StandardLocation.UPGRADE_MODULE_PATH, moduleName);
1108  }
1109
1110  /**
1111   * Get the module path roots for the
1112   * {@link StandardLocation#UPGRADE_MODULE_PATH upgrade module paths}.
1113   *
1114   * @return the roots in a map of module names to lists of roots, or an empty map if none were
1115   * found.
1116   * @since 0.1.0
1117   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1118   * this is being removed. You should instead call {@link #getModules(Location)}, passing
1119   * {@link StandardLocation#UPGRADE_MODULE_PATH} as the first parameter.
1120   */
1121  @Deprecated(forRemoval = true, since = "0.6.0")
1122  @SuppressWarnings("DeprecatedIsStillUsed")
1123  default Map<String, List<? extends PathRoot>> getUpgradeModulePathModules() {
1124    return getModules(StandardLocation.UPGRADE_MODULE_PATH);
1125  }
1126
1127  /**
1128   * Get the path roots for the {@link StandardLocation#SYSTEM_MODULES system modules}.
1129   *
1130   * @param moduleName the module name to get.
1131   * @return the roots in a collection, or an empty collection if none were found.
1132   * @since 0.1.0
1133   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1134   * this is being removed. You should instead call {@link #getModule(Location, String)}, passing
1135   * {@link StandardLocation#SYSTEM_MODULES} as the first parameter.
1136   */
1137  @Deprecated(forRemoval = true, since = "0.6.0")
1138  @SuppressWarnings("DeprecatedIsStillUsed")
1139  default List<? extends PathRoot> getSystemModulePathModule(String moduleName) {
1140    return getModule(StandardLocation.SYSTEM_MODULES, moduleName);
1141  }
1142
1143  /**
1144   * Get the module path roots for the {@link StandardLocation#SYSTEM_MODULES system modules}.
1145   *
1146   * @return the roots in a map of module names to lists of roots, or an empty map if none were
1147   * found.
1148   * @since 0.1.0
1149   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1150   * this is being removed. You should instead call {@link #getModules(Location)}, passing
1151   * {@link StandardLocation#SYSTEM_MODULES} as the first parameter.
1152   */
1153  @Deprecated(forRemoval = true, since = "0.6.0")
1154  @SuppressWarnings("DeprecatedIsStillUsed")
1155  default Map<String, List<? extends PathRoot>> getSystemModulePathModules() {
1156    return getModules(StandardLocation.SYSTEM_MODULES);
1157  }
1158
1159  /**
1160   * Get the path roots for the {@link StandardLocation#MODULE_PATH module path}.
1161   *
1162   * @param moduleName the module name to get.
1163   * @return the roots in a collection, or an empty collection if none were found.
1164   * @since 0.1.0
1165   */
1166  default List<? extends PathRoot> getModulePathModule(String moduleName) {
1167    return getModule(StandardLocation.MODULE_PATH, moduleName);
1168  }
1169
1170  /**
1171   * Get the module path roots for the {@link StandardLocation#MODULE_PATH module paths}.
1172   *
1173   * @return the roots in a map of module names to lists of roots, or an empty map if none were
1174   * found.
1175   * @since 0.1.0
1176   */
1177  default Map<String, List<? extends PathRoot>> getModulePathModules() {
1178    return getModules(StandardLocation.MODULE_PATH);
1179  }
1180
1181  /**
1182   * Get the path roots for the {@link StandardLocation#PATCH_MODULE_PATH patch module path}.
1183   *
1184   * @param moduleName the module name to get.
1185   * @return the roots in a collection, or an empty collection if none were found.
1186   * @since 0.1.0
1187   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1188   * this is being removed. You should instead call {@link #getModule(Location, String)}, passing
1189   * {@link StandardLocation#PATCH_MODULE_PATH} as the first parameter.
1190   */
1191  @Deprecated(forRemoval = true, since = "0.6.0")
1192  @SuppressWarnings("DeprecatedIsStillUsed")
1193  default List<? extends PathRoot> getPatchModulePathModule(String moduleName) {
1194    return getModule(StandardLocation.PATCH_MODULE_PATH, moduleName);
1195  }
1196
1197  /**
1198   * Get the module path roots for the
1199   * {@link StandardLocation#PATCH_MODULE_PATH patch module paths}.
1200   *
1201   * @return the roots in a map of module names to lists of roots, or an empty map if none were
1202   * found.
1203   * @since 0.1.0
1204   * @deprecated This is a specialist method that is usually not used. To keep the API simple,
1205   * this is being removed. You should instead call {@link #getModules(Location)}, passing
1206   * {@link StandardLocation#PATCH_MODULE_PATH} as the first parameter.
1207   */
1208  @Deprecated(forRemoval = true, since = "0.6.0")
1209  @SuppressWarnings("DeprecatedIsStillUsed")
1210  default Map<String, List<? extends PathRoot>> getPatchModulePathModules() {
1211    return getModules(StandardLocation.PATCH_MODULE_PATH);
1212  }
1213}