// Copyright 2018 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.importdeps; import static com.google.common.base.Preconditions.checkState; import com.google.auto.value.AutoValue; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultimap; import javax.annotation.Nullable; /** The resolution failure path. */ @AutoValue public abstract class ResolutionFailureChain { public static ResolutionFailureChain createMissingClass(String missingClass) { return new AutoValue_ResolutionFailureChain( ImmutableList.of(missingClass), /*resolutionStartClass=*/ null, /*parentChains=*/ ImmutableList.of()); } public static ResolutionFailureChain createWithParent( ClassInfo resolutionStartClass, ImmutableList parentChains) { Preconditions.checkArgument(!parentChains.isEmpty(), "The parentChains cannot be empty."); return new AutoValue_ResolutionFailureChain( parentChains .stream() .flatMap(chain -> chain.missingClasses().stream()) .sorted() .distinct() .collect(ImmutableList.toImmutableList()), resolutionStartClass, parentChains); } /** The missing class that causes the resolution failure. */ public abstract ImmutableList missingClasses(); /** The start of this resolution chain. */ @Nullable public abstract ClassInfo resolutionStartClass(); /** The resolution chain of the parent class. */ public abstract ImmutableList parentChains(); /** For all the missing classes, represent the first chains that lead to the missing classes. */ public ImmutableMultimap getMissingClassesWithSubclasses() { ImmutableMultimap.Builder result = ImmutableMultimap.builder(); getMissingClassesWithSubclasses(resolutionStartClass(), this.parentChains(), result); return result.build(); } private static void getMissingClassesWithSubclasses( ClassInfo subclass, ImmutableList parentChains, ImmutableMultimap.Builder result) { for (ResolutionFailureChain parentChain : parentChains) { if (parentChain.resolutionStartClass() == null) { checkState( parentChain.parentChains().isEmpty() && parentChain.missingClasses().size() == 1); result.put(parentChain.missingClasses().get(0), subclass); } else { checkState(!parentChain.parentChains().isEmpty()); getMissingClassesWithSubclasses( parentChain.resolutionStartClass(), parentChain.parentChains(), result); } } } }