blob: 443dcbcf4c569a34163046cffcd69f73876c105e [file] [log] [blame]
/*
* Copyright 2016 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.idea.blaze.base.sync.aspects;
import static java.util.stream.Collectors.toList;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.idea.blaze.base.ideinfo.AndroidIdeInfo;
import com.google.idea.blaze.base.ideinfo.AndroidSdkIdeInfo;
import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
import com.google.idea.blaze.base.ideinfo.CIdeInfo;
import com.google.idea.blaze.base.ideinfo.CToolchainIdeInfo;
import com.google.idea.blaze.base.ideinfo.Dependency;
import com.google.idea.blaze.base.ideinfo.Dependency.DependencyType;
import com.google.idea.blaze.base.ideinfo.GoIdeInfo;
import com.google.idea.blaze.base.ideinfo.JavaIdeInfo;
import com.google.idea.blaze.base.ideinfo.JavaToolchainIdeInfo;
import com.google.idea.blaze.base.ideinfo.JsIdeInfo;
import com.google.idea.blaze.base.ideinfo.LibraryArtifact;
import com.google.idea.blaze.base.ideinfo.ProtoLibraryLegacyInfo;
import com.google.idea.blaze.base.ideinfo.PyIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetKey;
import com.google.idea.blaze.base.ideinfo.TestIdeInfo;
import com.google.idea.blaze.base.ideinfo.TsIdeInfo;
import com.google.idea.blaze.base.model.primitives.ExecutionRootPath;
import com.google.idea.blaze.base.model.primitives.Kind;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.repackaged.devtools.intellij.ideinfo.IntellijIdeInfo;
import com.intellij.openapi.util.text.StringUtil;
import java.util.Collection;
import java.util.List;
import javax.annotation.Nullable;
/** Conversion functions from new aspect-style Bazel IDE info to ASWB internal classes. */
public class IdeInfoFromProtobuf {
@Nullable
public static TargetIdeInfo makeTargetIdeInfo(IntellijIdeInfo.TargetIdeInfo message) {
Kind kind = getKind(message);
if (kind == null) {
return null;
}
TargetKey key = getKey(message);
ArtifactLocation buildFile = getBuildFile(message);
final Collection<Dependency> dependencies;
if (message.getDepsCount() > 0) {
dependencies =
message.getDepsList().stream().map(IdeInfoFromProtobuf::makeDependency).collect(toList());
} else {
dependencies =
Lists.newArrayListWithCapacity(
message.getDependenciesCount() + message.getRuntimeDepsCount());
dependencies.addAll(
makeDependencyListFromLabelList(
message.getDependenciesList(), DependencyType.COMPILE_TIME));
dependencies.addAll(
makeDependencyListFromLabelList(message.getRuntimeDepsList(), DependencyType.RUNTIME));
}
Collection<String> tags = ImmutableList.copyOf(message.getTagsList());
Collection<ArtifactLocation> sources = Lists.newArrayList();
CIdeInfo cIdeInfo = null;
if (message.hasCIdeInfo()) {
cIdeInfo = makeCIdeInfo(message.getCIdeInfo());
sources.addAll(cIdeInfo.sources);
sources.addAll(cIdeInfo.headers);
sources.addAll(cIdeInfo.textualHeaders);
}
CToolchainIdeInfo cToolchainIdeInfo = null;
if (message.hasCToolchainIdeInfo()) {
cToolchainIdeInfo = makeCToolchainIdeInfo(message.getCToolchainIdeInfo());
}
JavaIdeInfo javaIdeInfo = null;
if (message.hasJavaIdeInfo()) {
javaIdeInfo = makeJavaIdeInfo(message.getJavaIdeInfo());
Collection<ArtifactLocation> javaSources =
makeArtifactLocationList(message.getJavaIdeInfo().getSourcesList());
sources.addAll(javaSources);
}
AndroidIdeInfo androidIdeInfo = null;
if (message.hasAndroidIdeInfo()) {
androidIdeInfo = makeAndroidIdeInfo(message.getAndroidIdeInfo());
}
AndroidSdkIdeInfo androidSdkIdeInfo = null;
if (message.hasAndroidSdkIdeInfo()) {
androidSdkIdeInfo = makeAndroidSdkIdeInfo(message.getAndroidSdkIdeInfo());
}
PyIdeInfo pyIdeInfo = null;
if (message.hasPyIdeInfo()) {
pyIdeInfo = makePyIdeInfo(message.getPyIdeInfo());
sources.addAll(pyIdeInfo.sources);
}
GoIdeInfo goIdeInfo = null;
if (message.hasGoIdeInfo()) {
goIdeInfo = makeGoIdeInfo(message.getGoIdeInfo());
sources.addAll(goIdeInfo.generatedSources);
}
JsIdeInfo jsIdeInfo = null;
if (message.hasJsIdeInfo()) {
jsIdeInfo = makeJsIdeInfo(message.getJsIdeInfo());
sources.addAll(jsIdeInfo.sources);
}
TsIdeInfo tsIdeInfo = null;
if (message.hasTsIdeInfo()) {
tsIdeInfo = makeTsIdeInfo(message.getTsIdeInfo());
sources.addAll(tsIdeInfo.sources);
}
TestIdeInfo testIdeInfo = null;
if (message.hasTestInfo()) {
testIdeInfo = makeTestIdeInfo(message.getTestInfo());
}
ProtoLibraryLegacyInfo protoLibraryLegacyInfo = null;
if (message.hasProtoLibraryLegacyJavaIdeInfo()) {
protoLibraryLegacyInfo =
makeProtoLibraryLegacyInfo(message.getProtoLibraryLegacyJavaIdeInfo());
}
JavaToolchainIdeInfo javaToolchainIdeInfo = null;
if (message.hasJavaToolchainIdeInfo()) {
javaToolchainIdeInfo = makeJavaToolchainIdeInfo(message.getJavaToolchainIdeInfo());
}
return new TargetIdeInfo(
key,
kind,
buildFile,
dependencies,
tags,
sources,
cIdeInfo,
cToolchainIdeInfo,
javaIdeInfo,
androidIdeInfo,
androidSdkIdeInfo,
pyIdeInfo,
goIdeInfo,
jsIdeInfo,
tsIdeInfo,
testIdeInfo,
protoLibraryLegacyInfo,
javaToolchainIdeInfo);
}
private static Collection<Dependency> makeDependencyListFromLabelList(
List<String> dependencyList, Dependency.DependencyType dependencyType) {
return dependencyList
.stream()
.map(dep -> new Dependency(TargetKey.forPlainTarget(Label.create(dep)), dependencyType))
.collect(toList());
}
private static TargetKey makeTargetKey(IntellijIdeInfo.TargetKey key) {
return TargetKey.forGeneralTarget(Label.create(key.getLabel()), key.getAspectIdsList());
}
private static Dependency makeDependency(IntellijIdeInfo.Dependency dep) {
return new Dependency(
makeTargetKey(dep.getTarget()), makeDependencyType(dep.getDependencyType()));
}
private static Dependency.DependencyType makeDependencyType(
IntellijIdeInfo.Dependency.DependencyType dependencyType) {
switch (dependencyType) {
case COMPILE_TIME:
return DependencyType.COMPILE_TIME;
case RUNTIME:
return DependencyType.RUNTIME;
default:
return DependencyType.COMPILE_TIME;
}
}
@Nullable
private static ArtifactLocation getBuildFile(IntellijIdeInfo.TargetIdeInfo message) {
if (message.hasBuildFileArtifactLocation()) {
return makeArtifactLocation(message.getBuildFileArtifactLocation());
}
return null;
}
private static CIdeInfo makeCIdeInfo(IntellijIdeInfo.CIdeInfo cIdeInfo) {
List<ArtifactLocation> sources = makeArtifactLocationList(cIdeInfo.getSourceList());
List<ArtifactLocation> headers = makeArtifactLocationList(cIdeInfo.getHeaderList());
List<ArtifactLocation> textualHeaders =
makeArtifactLocationList(cIdeInfo.getTextualHeaderList());
List<ExecutionRootPath> transitiveIncludeDirectories =
makeExecutionRootPathList(cIdeInfo.getTransitiveIncludeDirectoryList());
List<ExecutionRootPath> transitiveQuoteIncludeDirectories =
makeExecutionRootPathList(cIdeInfo.getTransitiveQuoteIncludeDirectoryList());
List<ExecutionRootPath> transitiveSystemIncludeDirectories =
makeExecutionRootPathList(cIdeInfo.getTransitiveSystemIncludeDirectoryList());
List<String> coptDefines;
List<ExecutionRootPath> coptIncludeDirectories;
if (cIdeInfo.getTargetCoptList().isEmpty()) {
coptDefines = ImmutableList.of();
coptIncludeDirectories = ImmutableList.of();
} else {
UnfilteredCompilerOptions compilerOptions =
UnfilteredCompilerOptions.builder()
.registerSingleOrSplitOption("-D")
.registerSingleOrSplitOption("-I")
.build(cIdeInfo.getTargetCoptList());
coptDefines = compilerOptions.getExtractedOptionValues("-D");
coptIncludeDirectories =
makeExecutionRootPathList(compilerOptions.getExtractedOptionValues("-I"));
}
CIdeInfo.Builder builder =
CIdeInfo.builder()
.addSources(sources)
.addHeaders(headers)
.addTextualHeaders(textualHeaders)
.addLocalDefines(coptDefines)
.addLocalIncludeDirectories(coptIncludeDirectories)
.addTransitiveIncludeDirectories(transitiveIncludeDirectories)
.addTransitiveQuoteIncludeDirectories(transitiveQuoteIncludeDirectories)
.addTransitiveDefines(cIdeInfo.getTransitiveDefineList())
.addTransitiveSystemIncludeDirectories(transitiveSystemIncludeDirectories);
return builder.build();
}
private static List<ExecutionRootPath> makeExecutionRootPathList(Iterable<String> relativePaths) {
List<ExecutionRootPath> workspacePaths = Lists.newArrayList();
for (String relativePath : relativePaths) {
workspacePaths.add(new ExecutionRootPath(relativePath));
}
return workspacePaths;
}
private static CToolchainIdeInfo makeCToolchainIdeInfo(
IntellijIdeInfo.CToolchainIdeInfo cToolchainIdeInfo) {
Collection<ExecutionRootPath> builtInIncludeDirectories =
makeExecutionRootPathList(cToolchainIdeInfo.getBuiltInIncludeDirectoryList());
ExecutionRootPath cppExecutable = new ExecutionRootPath(cToolchainIdeInfo.getCppExecutable());
ExecutionRootPath preprocessorExecutable =
new ExecutionRootPath(cToolchainIdeInfo.getPreprocessorExecutable());
UnfilteredCompilerOptions compilerOptions =
UnfilteredCompilerOptions.builder()
.registerSingleOrSplitOption("-isystem")
.build(cToolchainIdeInfo.getUnfilteredCompilerOptionList());
CToolchainIdeInfo.Builder builder =
CToolchainIdeInfo.builder()
.addBaseCompilerOptions(cToolchainIdeInfo.getBaseCompilerOptionList())
.addCCompilerOptions(cToolchainIdeInfo.getCOptionList())
.addCppCompilerOptions(cToolchainIdeInfo.getCppOptionList())
.addLinkOptions(cToolchainIdeInfo.getLinkOptionList())
.addBuiltInIncludeDirectories(builtInIncludeDirectories)
.setCppExecutable(cppExecutable)
.setPreprocessorExecutable(preprocessorExecutable)
.setTargetName(cToolchainIdeInfo.getTargetName())
.addUnfilteredCompilerOptions(compilerOptions.getUninterpretedOptions())
.addUnfilteredToolchainSystemIncludes(
makeExecutionRootPathList(compilerOptions.getExtractedOptionValues("-isystem")));
return builder.build();
}
private static JavaIdeInfo makeJavaIdeInfo(IntellijIdeInfo.JavaIdeInfo javaIdeInfo) {
return new JavaIdeInfo(
makeLibraryArtifactList(javaIdeInfo.getJarsList()),
makeLibraryArtifactList(javaIdeInfo.getGeneratedJarsList()),
javaIdeInfo.hasFilteredGenJar()
? makeLibraryArtifact(javaIdeInfo.getFilteredGenJar())
: null,
javaIdeInfo.hasPackageManifest()
? makeArtifactLocation(javaIdeInfo.getPackageManifest())
: null,
javaIdeInfo.hasJdeps() ? makeArtifactLocation(javaIdeInfo.getJdeps()) : null,
Strings.emptyToNull(javaIdeInfo.getMainClass()));
}
private static AndroidIdeInfo makeAndroidIdeInfo(IntellijIdeInfo.AndroidIdeInfo androidIdeInfo) {
return new AndroidIdeInfo(
makeArtifactLocationList(androidIdeInfo.getResourcesList()),
androidIdeInfo.getJavaPackage(),
androidIdeInfo.getGenerateResourceClass(),
androidIdeInfo.hasManifest() ? makeArtifactLocation(androidIdeInfo.getManifest()) : null,
androidIdeInfo.hasIdlJar() ? makeLibraryArtifact(androidIdeInfo.getIdlJar()) : null,
androidIdeInfo.hasResourceJar()
? makeLibraryArtifact(androidIdeInfo.getResourceJar())
: null,
androidIdeInfo.getHasIdlSources(),
!Strings.isNullOrEmpty(androidIdeInfo.getLegacyResources())
? Label.create(androidIdeInfo.getLegacyResources())
: null);
}
private static AndroidSdkIdeInfo makeAndroidSdkIdeInfo(
IntellijIdeInfo.AndroidSdkIdeInfo androidSdkIdeInfo) {
return new AndroidSdkIdeInfo(makeArtifactLocation(androidSdkIdeInfo.getAndroidJar()));
}
private static PyIdeInfo makePyIdeInfo(IntellijIdeInfo.PyIdeInfo info) {
return PyIdeInfo.builder().addSources(makeArtifactLocationList(info.getSourcesList())).build();
}
private static GoIdeInfo makeGoIdeInfo(IntellijIdeInfo.GoIdeInfo info) {
return GoIdeInfo.builder()
.addGeneratedSources(makeArtifactLocationList(info.getGeneratedSourcesList()))
.build();
}
private static JsIdeInfo makeJsIdeInfo(IntellijIdeInfo.JsIdeInfo info) {
return JsIdeInfo.builder().addSources(makeArtifactLocationList(info.getSourcesList())).build();
}
private static TsIdeInfo makeTsIdeInfo(IntellijIdeInfo.TsIdeInfo info) {
return TsIdeInfo.builder().addSources(makeArtifactLocationList(info.getSourcesList())).build();
}
private static TestIdeInfo makeTestIdeInfo(IntellijIdeInfo.TestInfo testInfo) {
String size = testInfo.getSize();
TestIdeInfo.TestSize testSize = TestIdeInfo.DEFAULT_RULE_TEST_SIZE;
if (!Strings.isNullOrEmpty(size)) {
switch (size) {
case "small":
testSize = TestIdeInfo.TestSize.SMALL;
break;
case "medium":
testSize = TestIdeInfo.TestSize.MEDIUM;
break;
case "large":
testSize = TestIdeInfo.TestSize.LARGE;
break;
case "enormous":
testSize = TestIdeInfo.TestSize.ENORMOUS;
break;
default:
break;
}
}
return new TestIdeInfo(testSize);
}
private static ProtoLibraryLegacyInfo makeProtoLibraryLegacyInfo(
IntellijIdeInfo.ProtoLibraryLegacyJavaIdeInfo protoLibraryLegacyJavaIdeInfo) {
final ProtoLibraryLegacyInfo.ApiFlavor apiFlavor;
if (protoLibraryLegacyJavaIdeInfo.getApiVersion() == 1) {
apiFlavor = ProtoLibraryLegacyInfo.ApiFlavor.VERSION_1;
} else {
switch (protoLibraryLegacyJavaIdeInfo.getApiFlavor()) {
case MUTABLE:
apiFlavor = ProtoLibraryLegacyInfo.ApiFlavor.MUTABLE;
break;
case IMMUTABLE:
apiFlavor = ProtoLibraryLegacyInfo.ApiFlavor.IMMUTABLE;
break;
case BOTH:
apiFlavor = ProtoLibraryLegacyInfo.ApiFlavor.BOTH;
break;
default:
apiFlavor = ProtoLibraryLegacyInfo.ApiFlavor.NONE;
break;
}
}
return new ProtoLibraryLegacyInfo(
apiFlavor,
makeLibraryArtifactList(protoLibraryLegacyJavaIdeInfo.getJars1List()),
makeLibraryArtifactList(protoLibraryLegacyJavaIdeInfo.getJarsMutableList()),
makeLibraryArtifactList(protoLibraryLegacyJavaIdeInfo.getJarsImmutableList()));
}
private static JavaToolchainIdeInfo makeJavaToolchainIdeInfo(
IntellijIdeInfo.JavaToolchainIdeInfo javaToolchainIdeInfo) {
ArtifactLocation javacJar =
javaToolchainIdeInfo.hasJavacJar()
? makeArtifactLocation(javaToolchainIdeInfo.getJavacJar())
: null;
return new JavaToolchainIdeInfo(
javaToolchainIdeInfo.getSourceVersion(), javaToolchainIdeInfo.getTargetVersion(), javacJar);
}
private static Collection<LibraryArtifact> makeLibraryArtifactList(
List<IntellijIdeInfo.LibraryArtifact> jarsList) {
ImmutableList.Builder<LibraryArtifact> builder = ImmutableList.builder();
for (IntellijIdeInfo.LibraryArtifact libraryArtifact : jarsList) {
LibraryArtifact lib = makeLibraryArtifact(libraryArtifact);
if (lib != null) {
builder.add(lib);
}
}
return builder.build();
}
@Nullable
private static LibraryArtifact makeLibraryArtifact(
IntellijIdeInfo.LibraryArtifact libraryArtifact) {
ArtifactLocation classJar =
libraryArtifact.hasJar() ? makeArtifactLocation(libraryArtifact.getJar()) : null;
ArtifactLocation iJar =
libraryArtifact.hasInterfaceJar()
? makeArtifactLocation(libraryArtifact.getInterfaceJar())
: null;
ArtifactLocation sourceJar =
libraryArtifact.hasSourceJar()
? makeArtifactLocation(libraryArtifact.getSourceJar())
: null;
if (iJar == null && classJar == null) {
// Failed to find ArtifactLocation file --
// presumably because it was removed from file system since blaze build
return null;
}
return new LibraryArtifact(iJar, classJar, sourceJar);
}
private static List<ArtifactLocation> makeArtifactLocationList(
List<IntellijIdeInfo.ArtifactLocation> sourcesList) {
ImmutableList.Builder<ArtifactLocation> builder = ImmutableList.builder();
for (IntellijIdeInfo.ArtifactLocation pbArtifactLocation : sourcesList) {
ArtifactLocation loc = makeArtifactLocation(pbArtifactLocation);
if (loc != null) {
builder.add(loc);
}
}
return builder.build();
}
@VisibleForTesting
@Nullable
public static ArtifactLocation makeArtifactLocation(
@Nullable IntellijIdeInfo.ArtifactLocation location) {
if (location == null) {
return null;
}
String relativePath = location.getRelativePath();
String rootExecutionPathFragment = location.getRootExecutionPathFragment();
if (!location.getIsNewExternalVersion() && location.getIsExternal()) {
// fix up incorrect paths created with older aspect version
// Note: bazel always uses the '/' separator here, even on windows.
List<String> components = StringUtil.split(relativePath, "/");
if (components.size() > 2) {
relativePath = Joiner.on('/').join(components.subList(2, components.size()));
String prefix = components.get(0) + "/" + components.get(1);
rootExecutionPathFragment =
rootExecutionPathFragment.isEmpty() ? prefix : rootExecutionPathFragment + "/" + prefix;
}
}
return ArtifactLocation.builder()
.setRootExecutionPathFragment(rootExecutionPathFragment)
.setRelativePath(relativePath)
.setIsSource(location.getIsSource())
.setIsExternal(location.getIsExternal())
.build();
}
@Nullable
static Kind getKind(IntellijIdeInfo.TargetIdeInfo message) {
String kindString = message.getKindString();
if (!Strings.isNullOrEmpty(kindString)) {
return Kind.fromString(kindString);
}
return null;
}
static TargetKey getKey(IntellijIdeInfo.TargetIdeInfo message) {
return message.hasKey()
? makeTargetKey(message.getKey())
: TargetKey.forPlainTarget(Label.create(message.getLabel()));
}
}