com.google.devtools.build.lib.query2.output.PreciseAspectResolver.java Source code

Java tutorial

Introduction

Here is the source code for com.google.devtools.build.lib.query2.output.PreciseAspectResolver.java

Source

// Copyright 2015 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.query2.output;

import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.Aspect;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.DependencyFilter;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.pkgcache.PackageProvider;
import com.google.devtools.build.lib.util.BinaryPredicate;

import java.util.LinkedHashSet;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Nullable;

/**
 * An aspect resolver that returns only those aspects that are possibly active given the rule
 * classes of direct dependencies.
 *
 * <p>Needs to load the packages that contain dependencies through attributes with aspects.
 */
public class PreciseAspectResolver implements AspectResolver {
    private final PackageProvider packageProvider;
    private final EventHandler eventHandler;

    public PreciseAspectResolver(PackageProvider packageProvider, EventHandler eventHandler) {
        this.packageProvider = packageProvider;
        this.eventHandler = eventHandler;
    }

    @Override
    public ImmutableMultimap<Attribute, Label> computeAspectDependencies(Target target,
            DependencyFilter dependencyFilter) throws InterruptedException {
        Multimap<Attribute, Label> result = LinkedListMultimap.create();
        if (target instanceof Rule) {
            Multimap<Attribute, Label> transitions = ((Rule) target)
                    .getTransitions(DependencyFilter.NO_NODEP_ATTRIBUTES);
            for (Entry<Attribute, Label> entry : transitions.entries()) {
                Target toTarget;
                try {
                    toTarget = packageProvider.getTarget(eventHandler, entry.getValue());
                    result.putAll(AspectDefinition.visitAspectsIfRequired(target, entry.getKey(), toTarget,
                            dependencyFilter));
                } catch (NoSuchThingException e) {
                    // Do nothing. One of target direct deps has an error. The dependency on the BUILD file
                    // (or one of the files included in it) will be reported in the query result of :BUILD.
                }
            }
        }
        return ImmutableMultimap.copyOf(result);
    }

    @Override
    public Set<Label> computeBuildFileDependencies(Package pkg, BuildFileDependencyMode mode)
            throws InterruptedException {
        Set<Label> result = new LinkedHashSet<>();
        result.addAll(mode.getDependencies(pkg));

        Set<PackageIdentifier> dependentPackages = new LinkedHashSet<>();
        // First compute with packages can possibly affect the aspect attributes of this package:
        // Iterate over all rules...
        for (Target target : pkg.getTargets()) {

            if (!(target instanceof Rule)) {
                continue;
            }

            // ...figure out which direct dependencies can possibly have aspects attached to them...
            Multimap<Attribute, Label> depsWithPossibleAspects = ((Rule) target)
                    .getTransitions(new BinaryPredicate<Rule, Attribute>() {
                        @Override
                        public boolean apply(@Nullable Rule rule, Attribute attribute) {
                            for (Aspect aspectWithParameters : attribute.getAspects(rule)) {
                                if (!aspectWithParameters.getDefinition().getAttributes().isEmpty()) {
                                    return true;
                                }
                            }

                            return false;
                        }
                    });

            // ...and add the package of the aspect.
            for (Label depLabel : depsWithPossibleAspects.values()) {
                dependentPackages.add(depLabel.getPackageIdentifier());
            }
        }

        // Then add all the subinclude labels of the packages thus found to the result.
        for (PackageIdentifier packageIdentifier : dependentPackages) {
            try {
                result.add(Label.create(packageIdentifier, "BUILD"));
                Package dependentPackage = packageProvider.getPackage(eventHandler, packageIdentifier);
                result.addAll(mode.getDependencies(dependentPackage));
            } catch (NoSuchPackageException e) {
                // If the package is not found, just add its BUILD file, which is already done above.
                // Hopefully this error is not raised when there is a syntax error in a subincluded file
                // or something.
            } catch (LabelSyntaxException e) {
                throw new IllegalStateException(e);
            }
        }

        return result;
    }
}