/*
* Copyright 2017-present Facebook, Inc.
*
* 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
*
* http://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 com.facebook.buck.jvm.java;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.RuleKeyAppendable;
import com.facebook.buck.rules.RuleKeyObjectSink;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import org.immutables.value.Value;
/**
* Describes the properties of a plugin to javac, either a {@link
* javax.annotation.processing.Processor} or a {@link com.sun.source.util.Plugin}. The classpath and
* input properties in particular can be expensive to compute, so this object should be cached when
* possible.
*/
@Value.Immutable
@BuckStyleImmutable
abstract class AbstractJavacPluginProperties implements RuleKeyAppendable {
@Value.NaturalOrder
public abstract ImmutableSortedSet<String> getProcessorNames();
@Value.NaturalOrder
public abstract ImmutableSortedSet<SourcePath> getClasspathEntries();
@Value.NaturalOrder
public abstract ImmutableSortedSet<SourcePath> getInputs();
public abstract ImmutableList<BuildRule> getClasspathDeps();
public abstract boolean getCanReuseClassLoader();
public abstract boolean getDoesNotAffectAbi();
public abstract boolean getSupportsAbiGenerationFromSource();
public boolean isEmpty() {
return getProcessorNames().isEmpty() && getClasspathEntries().isEmpty();
}
public ResolvedJavacPluginProperties resolve(
ProjectFilesystem filesystem, SourcePathResolver resolver) {
return new ResolvedJavacPluginProperties(this, filesystem, resolver);
}
@Override
public void appendToRuleKey(RuleKeyObjectSink sink) {
// classpathEntries is not necessary because it is derived from inputs, which is below
sink.setReflectively("processors", getProcessorNames()).setReflectively("inputs", getInputs());
}
abstract static class Builder {
public abstract Builder addInputs(SourcePath... elements);
public abstract Builder addClasspathEntries(SourcePath... elements);
public abstract Builder addAllClasspathEntries(Iterable<? extends SourcePath> elements);
public abstract Builder addClasspathDeps(BuildRule... elements);
public abstract Builder addAllClasspathDeps(Iterable<? extends BuildRule> elements);
public abstract JavacPluginProperties build();
public JavacPluginProperties.Builder addDep(BuildRule rule) {
addClasspathDeps(rule);
if (rule.getClass().isAnnotationPresent(BuildsAnnotationProcessor.class)) {
SourcePath outputSourcePath = rule.getSourcePathToOutput();
if (outputSourcePath != null) {
addInputs(outputSourcePath);
addClasspathEntries(outputSourcePath);
}
} else if (rule instanceof HasClasspathEntries) {
HasClasspathEntries hasClasspathEntries = (HasClasspathEntries) rule;
ImmutableSet<JavaLibrary> entries = hasClasspathEntries.getTransitiveClasspathDeps();
addAllClasspathDeps(entries);
for (JavaLibrary entry : entries) {
// Libraries may merely re-export other libraries' class paths, instead of having one
// itself. In such cases do not add the library itself, and just move on.
if (entry.getSourcePathToOutput() != null) {
addInputs(entry.getSourcePathToOutput());
}
}
addAllClasspathEntries(hasClasspathEntries.getTransitiveClasspaths());
} else {
throw new HumanReadableException(
"%s is not a legal dependency for an annotation processor or compiler plugin; "
+ "must refer only to prebuilt jar, java binary, or java library targets.",
rule.getFullyQualifiedName());
}
return (JavacPluginProperties.Builder) this;
}
}
}