/*
 * Copyright 2017-2020 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micronaut.inject.visitor;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import io.micronaut.core.annotation.Experimental;
import io.micronaut.core.convert.value.MutableConvertibleValues;
import io.micronaut.inject.ast.ClassElement;
import io.micronaut.inject.ast.Element;
import io.micronaut.inject.writer.ClassWriterOutputVisitor;
import io.micronaut.inject.writer.GeneratedFile;

import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;

Provides a way for TypeElementVisitor classes to log messages during compilation and fail compilation.
Author:James Kleeh, Graeme Rocher
Since:1.0
/** * Provides a way for {@link TypeElementVisitor} classes to log messages during compilation and fail compilation. * * @author James Kleeh * @author Graeme Rocher * @since 1.0 */
public interface VisitorContext extends MutableConvertibleValues<Object>, ClassWriterOutputVisitor { String MICRONAUT_BASE_OPTION_NAME = "micronaut"; String MICRONAUT_PROCESSING_PROJECT_DIR = "micronaut.processing.project.dir"; String MICRONAUT_PROCESSING_GROUP = "micronaut.processing.group"; String MICRONAUT_PROCESSING_MODULE = "micronaut.processing.module";
Allows printing informational messages.
Params:
  • message – The message
  • element – The element
/** * Allows printing informational messages. * * @param message The message * @param element The element */
void info(String message, @Nullable Element element);
Allows printing informational messages.
Params:
  • message – The message
/** * Allows printing informational messages. * * @param message The message */
void info(String message);
Allows failing compilation for a given element with the given message.
Params:
  • message – The message
  • element – The element
/** * Allows failing compilation for a given element with the given message. * * @param message The message * @param element The element */
void fail(String message, @Nullable Element element);
Allows printing a warning for the given message and element.
Params:
  • message – The message
  • element – The element
/** * Allows printing a warning for the given message and element. * * @param message The message * @param element The element */
void warn(String message, @Nullable Element element);
Visit a file within the META-INF directory.
Params:
  • path – The path to the file
Returns:An optional file it was possible to create it
/** * Visit a file within the META-INF directory. * * @param path The path to the file * @return An optional file it was possible to create it */
@Override @Experimental Optional<GeneratedFile> visitMetaInfFile(String path);
Visit a file that will be located within the generated source directory.
Params:
  • path – The path to the file
Returns:An optional file it was possible to create it
/** * Visit a file that will be located within the generated source directory. * * @param path The path to the file * @return An optional file it was possible to create it */
@Override @Experimental Optional<GeneratedFile> visitGeneratedFile(String path);
Obtain a set of resources from the user classpath.
Params:
  • path – The path
Returns:An iterable of resources
/** * Obtain a set of resources from the user classpath. * * @param path The path * @return An iterable of resources */
@Experimental default @NonNull Iterable<URL> getClasspathResources(@NonNull String path) { return Collections.emptyList(); }
Obtain the project directory.
Returns:An optional wrapping the project directory
/** * Obtain the project directory. * * @return An optional wrapping the project directory */
default Optional<Path> getProjectDir() { Optional<Path> projectDir = get(MICRONAUT_PROCESSING_PROJECT_DIR, Path.class); if (projectDir.isPresent()) { return projectDir; } // let's find the projectDir Optional<GeneratedFile> dummyFile = visitGeneratedFile("dummy"); if (dummyFile.isPresent()) { URI uri = dummyFile.get().toURI(); // happens in tests 'mem:///CLASS_OUTPUT/dummy' if (uri.getScheme() != null && !uri.getScheme().equals("mem")) { // assume files are generated in 'build' or 'target' directories Path dummy = Paths.get(uri).normalize(); while (dummy != null) { Path dummyFileName = dummy.getFileName(); if (dummyFileName != null && ("build".equals(dummyFileName.toString()) || "target".equals(dummyFileName.toString()))) { projectDir = Optional.ofNullable(dummy.getParent()); put(MICRONAUT_PROCESSING_PROJECT_DIR, dummy.getParent()); break; } dummy = dummy.getParent(); } } } return projectDir; }
Provide the Path to the annotation processing classes output directory, i.e. the parent of META-INF.

This might, for example, be used as a convenience for TypeElementVisitor classes to provide relative path strings to addGeneratedResource(String)

Path resource = ... // absolute path to the resource
visitorContext.getClassesOutputPath().ifPresent(path ->
    visitorContext.addGeneratedResource(path.relativize(resource).toString()));
Returns:Path pointing to the classes output directory
/** * Provide the Path to the annotation processing classes output directory, i.e. the parent of META-INF. * * <p>This might, for example, be used as a convenience for {@link TypeElementVisitor} classes to provide * relative path strings to {@link VisitorContext#addGeneratedResource(String)}</p> * <pre> * Path resource = ... // absolute path to the resource * visitorContext.getClassesOutputPath().ifPresent(path -> * visitorContext.addGeneratedResource(path.relativize(resource).toString())); * </pre> * * @return Path pointing to the classes output directory */
@Experimental default Optional<Path> getClassesOutputPath() { Optional<GeneratedFile> dummy = visitMetaInfFile("dummy"); if (dummy.isPresent()) { // we want the parent directory of META-INF/dummy Path classesOutputDir = Paths.get(dummy.get().toURI()).getParent().getParent(); return Optional.of(classesOutputDir); } return Optional.empty(); }
This method will lookup another class element by name. If it cannot be found an empty optional will be returned.
Params:
  • name – The name
Returns:The class element
/** * This method will lookup another class element by name. If it cannot be found an empty optional will be returned. * * @param name The name * @return The class element */
default Optional<ClassElement> getClassElement(String name) { return Optional.empty(); }
This method will lookup another class element by name. If it cannot be found an empty optional will be returned.
Params:
  • type – The name
Returns:The class element
/** * This method will lookup another class element by name. If it cannot be found an empty optional will be returned. * * @param type The name * @return The class element */
default Optional<ClassElement> getClassElement(Class<?> type) { if (type != null) { return getClassElement(type.getName()); } return Optional.empty(); }
Find all the classes within the given package and having the given annotation.
Params:
  • aPackage – The package
  • stereotypes – The stereotypes
Returns:The class elements
/** * Find all the classes within the given package and having the given annotation. * @param aPackage The package * @param stereotypes The stereotypes * @return The class elements */
default @NonNull ClassElement[] getClassElements(@NonNull String aPackage, @NonNull String... stereotypes) { return new ClassElement[0]; }
The annotation processor environment custom options.

All options names MUST start with MICRONAUT_BASE_OPTION_NAME

See Also:
Returns:A Map with annotation processor runtime options
/** * The annotation processor environment custom options. * <p><b>All options names MUST start with {@link VisitorContext#MICRONAUT_BASE_OPTION_NAME}</b></p> * @return A Map with annotation processor runtime options * @see javax.annotation.processing.ProcessingEnvironment#getOptions() */
@Experimental default Map<String, String> getOptions() { return Collections.emptyMap(); }
Provide a collection of generated classpath resources that other TypeElement visitors might want to consume. The generated resources are intended to be strings paths relative to the classpath root.
Returns:a possibly empty collection of resource paths
/** * Provide a collection of generated classpath resources that other TypeElement visitors might want to consume. * The generated resources are intended to be strings paths relative to the classpath root. * * @return a possibly empty collection of resource paths */
@Experimental default Collection<String> getGeneratedResources() { info("EXPERIMENTAL: Compile time resource contribution to the context is experimental", null); return Collections.emptyList(); }
Some TypeElementVisitors generate classpath resources that other visitors might be interested in. The generated resources are intended to be strings paths relative to the classpath root
Params:
  • resource – the relative path to add
/** * Some TypeElementVisitors generate classpath resources that other visitors might be interested in. * The generated resources are intended to be strings paths relative to the classpath root * * @param resource the relative path to add */
@Experimental default void addGeneratedResource(String resource) { info("EXPERIMENTAL: Compile time resource contribution to the context is experimental", null); } }