use of com.google.devtools.build.lib.syntax.ParserInputSource in project bazel by bazelbuild.
the class PackageFunction method loadPackage.
/**
* Constructs a {@link Package} object for the given package using legacy package loading.
* Note that the returned package may be in error.
*
* <p>May return null if the computation has to be restarted.
*
* <p>Exactly one of {@code replacementContents} and {@code buildFileValue} will be
* non-{@code null}. The former indicates that we have a faux BUILD file with the given contents
* and the latter indicates that we have a legitimate BUILD file and should actually do
* preprocessing.
*/
@Nullable
private CacheEntryWithGlobDeps<Package.Builder> loadPackage(String workspaceName, @Nullable String replacementContents, PackageIdentifier packageId, Path buildFilePath, @Nullable FileValue buildFileValue, RuleVisibility defaultVisibility, List<Statement> preludeStatements, Path packageRoot, Environment env) throws InterruptedException, PackageFunctionException {
CacheEntryWithGlobDeps<Package.Builder> packageFunctionCacheEntry = packageFunctionCache.getIfPresent(packageId);
if (packageFunctionCacheEntry == null) {
profiler.startTask(ProfilerTask.CREATE_PACKAGE, packageId.toString());
if (packageProgress != null) {
packageProgress.startReadPackage(packageId);
}
try {
CacheEntryWithGlobDeps<AstAfterPreprocessing> astCacheEntry = astCache.getIfPresent(packageId);
if (astCacheEntry == null) {
if (showLoadingProgress.get()) {
env.getListener().handle(Event.progress("Loading package: " + packageId));
}
// We use a LegacyGlobber that doesn't sort the matches for each individual glob pattern,
// since we want to sort the final result anyway.
LegacyGlobber legacyGlobber = packageFactory.createLegacyGlobberThatDoesntSort(buildFilePath.getParentDirectory(), packageId, packageLocator);
SkyframeHybridGlobber skyframeGlobber = new SkyframeHybridGlobber(packageId, packageRoot, env, legacyGlobber);
Preprocessor.Result preprocessingResult;
if (replacementContents == null) {
Preconditions.checkNotNull(buildFileValue, packageId);
byte[] buildFileBytes;
try {
buildFileBytes = buildFileValue.isSpecialFile() ? FileSystemUtils.readContent(buildFilePath) : FileSystemUtils.readWithKnownFileSize(buildFilePath, buildFileValue.getSize());
} catch (IOException e) {
// transient.
throw new PackageFunctionException(new BuildFileContainsErrorsException(packageId, e.getMessage()), Transience.TRANSIENT);
}
try {
preprocessingResult = packageFactory.preprocess(buildFilePath, packageId, buildFileBytes, skyframeGlobber);
} catch (IOException e) {
throw new PackageFunctionException(new BuildFileContainsErrorsException(packageId, "preprocessing failed" + e.getMessage(), e), Transience.TRANSIENT);
}
} else {
ParserInputSource replacementSource = ParserInputSource.create(replacementContents, buildFilePath.asFragment());
preprocessingResult = Preprocessor.Result.noPreprocessing(replacementSource);
}
StoredEventHandler astParsingEventHandler = new StoredEventHandler();
BuildFileAST ast = PackageFactory.parseBuildFile(packageId, preprocessingResult.result, preludeStatements, astParsingEventHandler);
// If no globs were fetched during preprocessing, then there's no need to reuse the
// legacy globber instance during BUILD file evaluation since the performance argument
// below does not apply.
Set<SkyKey> globDepsRequested = skyframeGlobber.getGlobDepsRequested();
LegacyGlobber legacyGlobberToStore = globDepsRequested.isEmpty() ? null : legacyGlobber;
astCacheEntry = new CacheEntryWithGlobDeps<>(new AstAfterPreprocessing(preprocessingResult, ast, astParsingEventHandler), globDepsRequested, legacyGlobberToStore);
astCache.put(packageId, astCacheEntry);
}
AstAfterPreprocessing astAfterPreprocessing = astCacheEntry.value;
Set<SkyKey> globDepsRequestedDuringPreprocessing = astCacheEntry.globDepKeys;
SkylarkImportResult importResult;
try {
importResult = fetchImportsFromBuildFile(buildFilePath, packageId, astAfterPreprocessing.ast, env, skylarkImportLookupFunctionForInlining);
} catch (NoSuchPackageException e) {
throw new PackageFunctionException(e, Transience.PERSISTENT);
} catch (InterruptedException e) {
astCache.invalidate(packageId);
throw e;
}
if (importResult == null) {
return null;
}
astCache.invalidate(packageId);
// If a legacy globber was used to evaluate globs during preprocessing, it's important that
// we reuse that globber during BUILD file evaluation for performance, in the case that
// globs were fetched lazily during preprocessing. See Preprocessor.Factory#considersGlobs.
LegacyGlobber legacyGlobber = astCacheEntry.legacyGlobber != null ? astCacheEntry.legacyGlobber : packageFactory.createLegacyGlobber(buildFilePath.getParentDirectory(), packageId, packageLocator);
SkyframeHybridGlobber skyframeGlobber = new SkyframeHybridGlobber(packageId, packageRoot, env, legacyGlobber);
Package.Builder pkgBuilder = packageFactory.createPackageFromPreprocessingAst(workspaceName, packageId, buildFilePath, astAfterPreprocessing, importResult.importMap, importResult.fileDependencies, defaultVisibility, skyframeGlobber);
Set<SkyKey> globDepsRequested = ImmutableSet.<SkyKey>builder().addAll(globDepsRequestedDuringPreprocessing).addAll(skyframeGlobber.getGlobDepsRequested()).build();
packageFunctionCacheEntry = new CacheEntryWithGlobDeps<>(pkgBuilder, globDepsRequested, null);
numPackagesLoaded.incrementAndGet();
if (packageProgress != null) {
packageProgress.doneReadPackage(packageId);
}
packageFunctionCache.put(packageId, packageFunctionCacheEntry);
} finally {
profiler.completeTask(ProfilerTask.CREATE_PACKAGE);
}
}
return packageFunctionCacheEntry;
}
use of com.google.devtools.build.lib.syntax.ParserInputSource in project bazel by bazelbuild.
the class SubincludePreprocessorTest method testPreprocessingInclude.
@Test
public void testPreprocessingInclude() throws Exception {
ParserInputSource in = createInputSource("subinclude('//foo:bar')");
scratch.file("foo/BUILD");
scratch.file("foo/bar", "genrule('turtle1')", "subinclude('//foo:baz')");
scratch.file("foo/baz", "genrule('turtle2')");
String out = assertPreprocessingSucceeds(in);
assertThat(out).containsMatch("turtle1");
assertThat(out).containsMatch("turtle2");
assertThat(out).containsMatch("mocksubinclude\\('//foo:bar', *'/workspace/foo/bar'\\)");
assertThat(out).containsMatch("mocksubinclude\\('//foo:baz', *'/workspace/foo/baz'\\)");
}
use of com.google.devtools.build.lib.syntax.ParserInputSource in project bazel by bazelbuild.
the class SubincludePreprocessorTest method testError.
@Test
public void testError() throws Exception {
ParserInputSource in = createInputSource("subinclude('//foo:bar')");
scratch.file("foo/BUILD");
scratch.file("foo/bar", SubincludePreprocessor.TRANSIENT_ERROR);
try {
preprocess(in, "path/to/package");
fail();
} catch (IOException e) {
// Expected.
}
}
use of com.google.devtools.build.lib.syntax.ParserInputSource in project bazel by bazelbuild.
the class SubincludePreprocessorTest method createInputSource.
private ParserInputSource createInputSource(String... lines) throws Exception {
Path buildFile = packageRoot.getChild("BUILD");
writeIsoLatin1(buildFile, lines);
ParserInputSource in = ParserInputSource.create(buildFile);
return in;
}
use of com.google.devtools.build.lib.syntax.ParserInputSource in project bazel by bazelbuild.
the class SubincludePreprocessorTest method testSubincludeNotFound.
@Test
public void testSubincludeNotFound() throws Exception {
ParserInputSource in = createInputSource("subinclude('//nonexistent:bar')");
scratch.file("foo/BUILD");
String out = assertPreprocessingSucceeds(in);
assertThat(out).containsMatch("mocksubinclude\\('//nonexistent:bar', *''\\)");
assertContainsEvent("Cannot find subincluded file");
}
Aggregations