| /* |
| * Copyright 2012-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.java; |
| |
| import com.facebook.buck.io.ProjectFilesystem; |
| import com.facebook.buck.model.BuildTarget; |
| import com.facebook.buck.rules.BuildRule; |
| import com.facebook.buck.rules.RuleKey; |
| import com.facebook.buck.rules.RuleKeyAppendable; |
| import com.facebook.buck.util.BuckConstant; |
| import com.facebook.buck.util.HumanReadableException; |
| import com.google.common.base.Preconditions; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.ImmutableSortedSet; |
| import com.google.common.collect.Sets; |
| |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Collection; |
| import java.util.Set; |
| |
| import javax.annotation.Nullable; |
| |
| /** |
| * Information for annotation processing. |
| * |
| * Annotation processing involves a set of processors, their classpath(s), and a few other |
| * command-line options for javac. We want to be able to specify all this various information |
| * in a BUCK configuration file and use it when we generate the javac command. This facilitates |
| * threading the information through buck in a more descriptive package rather than passing all |
| * the components separately. |
| */ |
| public class AnnotationProcessingParams implements RuleKeyAppendable { |
| public static final AnnotationProcessingParams EMPTY = new AnnotationProcessingParams( |
| /* owner target */ null, |
| /* project filesystem */ null, |
| ImmutableSet.<Path>of(), |
| ImmutableSet.<String>of(), |
| ImmutableSet.<String>of(), |
| ImmutableSortedSet.<BuildRule>of(), |
| false); |
| |
| @Nullable |
| private final BuildTarget ownerTarget; |
| @Nullable |
| private final ProjectFilesystem filesystem; |
| private final ImmutableSortedSet<Path> searchPathElements; |
| private final ImmutableSortedSet<String> names; |
| private final ImmutableSortedSet<String> parameters; |
| private final ImmutableSortedSet<BuildRule> rules; |
| private final boolean processOnly; |
| |
| private AnnotationProcessingParams( |
| @Nullable BuildTarget ownerTarget, |
| @Nullable ProjectFilesystem filesystem, |
| Set<Path> searchPathElements, |
| Set<String> names, |
| Set<String> parameters, |
| Set<BuildRule> rules, |
| boolean processOnly) { |
| this.ownerTarget = ownerTarget; |
| this.filesystem = filesystem; |
| this.searchPathElements = ImmutableSortedSet.copyOf(searchPathElements); |
| this.names = ImmutableSortedSet.copyOf(names); |
| this.parameters = ImmutableSortedSet.copyOf(parameters); |
| this.rules = ImmutableSortedSet.copyOf(rules); |
| this.processOnly = processOnly; |
| |
| if (!isEmpty() && ownerTarget != null) { |
| Preconditions.checkNotNull(filesystem); |
| } |
| } |
| |
| private Path getGeneratedSrcFolder() { |
| Preconditions.checkNotNull(filesystem); |
| return Paths.get( |
| String.format( |
| "%s/%s__%s_gen__", |
| BuckConstant.ANNOTATION_DIR, |
| Preconditions.checkNotNull(ownerTarget).getBasePathWithSlash(), |
| ownerTarget.getShortNameAndFlavorPostfix())); |
| } |
| |
| public boolean isEmpty() { |
| return searchPathElements.isEmpty() && names.isEmpty() && parameters.isEmpty(); |
| } |
| |
| public ImmutableSortedSet<Path> getSearchPathElements() { |
| return searchPathElements; |
| } |
| |
| public ImmutableSortedSet<String> getNames() { |
| return names; |
| } |
| |
| public ImmutableSortedSet<String> getParameters() { |
| return parameters; |
| } |
| |
| @Override |
| public RuleKey.Builder appendToRuleKey(RuleKey.Builder builder, String key) { |
| if (!isEmpty()) { |
| // searchPathElements is not needed here since it comes from rules, which is appended below. |
| String owner = (ownerTarget == null) ? null : ownerTarget.getFullyQualifiedName(); |
| builder.setReflectively(key + ".owner", owner) |
| .setReflectively(key + ".names", names) |
| .setReflectively(key + ".parameters", parameters) |
| .setReflectively(key + ".processOnly", processOnly); |
| |
| ImmutableList.Builder<String> ruleKeyStrings = ImmutableList.builder(); |
| for (BuildRule rule : rules) { |
| ruleKeyStrings.add(rule.getRuleKey().toString()); |
| } |
| builder.setReflectively(key + ".annotationProcessorRuleKeys", ruleKeyStrings.build()); |
| } |
| |
| return builder; |
| } |
| |
| public boolean getProcessOnly() { |
| return processOnly; |
| } |
| |
| @Nullable |
| public Path getGeneratedSourceFolderName() { |
| if ((ownerTarget != null) && !isEmpty()) { |
| return getGeneratedSrcFolder(); |
| } else { |
| return null; |
| } |
| } |
| |
| public static class Builder { |
| @Nullable |
| private BuildTarget ownerTarget; |
| @Nullable |
| private ProjectFilesystem filesystem; |
| private Set<BuildRule> rules = Sets.newHashSet(); |
| private Set<String> names = Sets.newHashSet(); |
| private Set<String> parameters = Sets.newHashSet(); |
| private boolean processOnly; |
| |
| public Builder setOwnerTarget(BuildTarget owner) { |
| ownerTarget = owner; |
| return this; |
| } |
| |
| public Builder addProcessorBuildTarget(BuildRule rule) { |
| rules.add(rule); |
| return this; |
| } |
| |
| public Builder addAllProcessors(Collection<? extends String> processorNames) { |
| names.addAll(processorNames); |
| return this; |
| } |
| |
| public Builder addParameter(String parameter) { |
| parameters.add(parameter); |
| return this; |
| } |
| |
| public Builder setProcessOnly(boolean processOnly) { |
| this.processOnly = processOnly; |
| return this; |
| } |
| |
| public Builder setProjectFilesystem(ProjectFilesystem filesystem) { |
| this.filesystem = filesystem; |
| return this; |
| } |
| |
| public AnnotationProcessingParams build() { |
| if (names.isEmpty() && rules.isEmpty() && parameters.isEmpty()) { |
| return EMPTY; |
| } |
| |
| Set<Path> searchPathElements = Sets.newHashSet(); |
| |
| for (BuildRule rule : this.rules) { |
| if (rule.getClass().isAnnotationPresent(BuildsAnnotationProcessor.class)) { |
| Path pathToOutput = rule.getPathToOutputFile(); |
| if (pathToOutput != null) { |
| searchPathElements.add(pathToOutput); |
| } |
| } else if (rule instanceof HasClasspathEntries) { |
| searchPathElements.addAll( |
| ((HasClasspathEntries) rule).getTransitiveClasspathEntries().values()); |
| } else { |
| throw new HumanReadableException( |
| "%1$s: Error adding '%2$s' to annotation_processing_deps: " + |
| "must refer only to prebuilt jar, java binary, or java library targets.", |
| ownerTarget, |
| rule.getFullyQualifiedName()); |
| } |
| } |
| |
| return new AnnotationProcessingParams( |
| ownerTarget, |
| filesystem, |
| searchPathElements, |
| names, |
| parameters, |
| ImmutableSortedSet.copyOf(this.rules), |
| processOnly); |
| } |
| } |
| } |