Search in sources :

Example 1 with ParserInputSource

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;
}
Also used : ParserInputSource(com.google.devtools.build.lib.syntax.ParserInputSource) SkyKey(com.google.devtools.build.skyframe.SkyKey) BuildFileContainsErrorsException(com.google.devtools.build.lib.packages.BuildFileContainsErrorsException) LegacyGlobber(com.google.devtools.build.lib.packages.PackageFactory.LegacyGlobber) AstAfterPreprocessing(com.google.devtools.build.lib.packages.Preprocessor.AstAfterPreprocessing) IOException(java.io.IOException) StoredEventHandler(com.google.devtools.build.lib.events.StoredEventHandler) NoSuchPackageException(com.google.devtools.build.lib.packages.NoSuchPackageException) Preprocessor(com.google.devtools.build.lib.packages.Preprocessor) Package(com.google.devtools.build.lib.packages.Package) BuildFileAST(com.google.devtools.build.lib.syntax.BuildFileAST) Nullable(javax.annotation.Nullable)

Example 2 with ParserInputSource

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'\\)");
}
Also used : ParserInputSource(com.google.devtools.build.lib.syntax.ParserInputSource) Test(org.junit.Test)

Example 3 with ParserInputSource

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.
    }
}
Also used : ParserInputSource(com.google.devtools.build.lib.syntax.ParserInputSource) IOException(java.io.IOException) Test(org.junit.Test)

Example 4 with ParserInputSource

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;
}
Also used : Path(com.google.devtools.build.lib.vfs.Path) ParserInputSource(com.google.devtools.build.lib.syntax.ParserInputSource)

Example 5 with ParserInputSource

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");
}
Also used : ParserInputSource(com.google.devtools.build.lib.syntax.ParserInputSource) Test(org.junit.Test)

Aggregations

ParserInputSource (com.google.devtools.build.lib.syntax.ParserInputSource)5 Test (org.junit.Test)3 IOException (java.io.IOException)2 StoredEventHandler (com.google.devtools.build.lib.events.StoredEventHandler)1 BuildFileContainsErrorsException (com.google.devtools.build.lib.packages.BuildFileContainsErrorsException)1 NoSuchPackageException (com.google.devtools.build.lib.packages.NoSuchPackageException)1 Package (com.google.devtools.build.lib.packages.Package)1 LegacyGlobber (com.google.devtools.build.lib.packages.PackageFactory.LegacyGlobber)1 Preprocessor (com.google.devtools.build.lib.packages.Preprocessor)1 AstAfterPreprocessing (com.google.devtools.build.lib.packages.Preprocessor.AstAfterPreprocessing)1 BuildFileAST (com.google.devtools.build.lib.syntax.BuildFileAST)1 Path (com.google.devtools.build.lib.vfs.Path)1 SkyKey (com.google.devtools.build.skyframe.SkyKey)1 Nullable (javax.annotation.Nullable)1