/*
* Copyright 2016-present Facebook, Inc.
*
* 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.facebook.buck.parser;
import com.facebook.buck.cli.BuckConfig;
import com.facebook.buck.config.ConfigView;
import com.facebook.buck.io.ExecutableFinder;
import com.facebook.buck.python.PythonBuckConfig;
import com.facebook.buck.util.WatchmanWatcher;
import com.facebook.buck.util.immutables.BuckStyleImmutable;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
import java.util.Optional;
import org.immutables.value.Value;
@Value.Immutable(builder = false, copy = false)
@BuckStyleImmutable
abstract class AbstractParserConfig implements ConfigView<BuckConfig> {
public static final boolean DEFAULT_ALLOW_EMPTY_GLOBS = true;
public static final String DEFAULT_BUILD_FILE_NAME = "BUCK";
public static final String BUILDFILE_SECTION_NAME = "buildfile";
public static final String INCLUDES_PROPERTY_NAME = "includes";
private static final long NUM_PARSING_THREADS_DEFAULT = 1L;
public enum GlobHandler {
PYTHON,
WATCHMAN,
MERCURIAL,
;
}
public enum WatchmanGlobSanityCheck {
NONE,
STAT,
;
}
public enum AllowSymlinks {
ALLOW,
WARN,
FORBID,
;
}
public enum BuildFileSearchMethod {
FILESYSTEM_CRAWL,
WATCHMAN,
;
}
/** Controls whether default flavors should be applied to unflavored targets. */
public enum ApplyDefaultFlavorsMode {
ENABLED,
DISABLED
}
@Value.Lazy
public boolean getAllowEmptyGlobs() {
return getDelegate()
.getValue("build", "allow_empty_globs")
.map(Boolean::parseBoolean)
.orElse(DEFAULT_ALLOW_EMPTY_GLOBS);
}
@Value.Lazy
public String getBuildFileName() {
return getDelegate().getValue(BUILDFILE_SECTION_NAME, "name").orElse(DEFAULT_BUILD_FILE_NAME);
}
/**
* A (possibly empty) sequence of paths to files that should be included by default when
* evaluating a build file.
*/
@Value.Lazy
public Iterable<String> getDefaultIncludes() {
ImmutableMap<String, String> entries =
getDelegate().getEntriesForSection(BUILDFILE_SECTION_NAME);
String includes = Strings.nullToEmpty(entries.get(INCLUDES_PROPERTY_NAME));
return Splitter.on(' ').trimResults().omitEmptyStrings().split(includes);
}
@Value.Lazy
public boolean getEnforceBuckPackageBoundary() {
return getDelegate().getBooleanValue("project", "check_package_boundary", true);
}
/** A list of absolute paths under which buck package boundary checks should not be performed. */
@Value.Lazy
public ImmutableList<Path> getBuckPackageBoundaryExceptions() {
return getDelegate()
.getOptionalPathList("project", "package_boundary_exceptions")
.orElse(ImmutableList.of());
}
@Value.Lazy
public Optional<ImmutableList<Path>> getReadOnlyPaths() {
return getDelegate().getOptionalPathList("project", "read_only_paths");
}
@Value.Lazy
public AllowSymlinks getAllowSymlinks() {
return getDelegate()
.getEnum("project", "allow_symlinks", AllowSymlinks.class)
.orElse(AllowSymlinks.WARN);
}
@Value.Lazy
public Optional<BuildFileSearchMethod> getBuildFileSearchMethod() {
return getDelegate()
.getEnum("project", "build_file_search_method", BuildFileSearchMethod.class);
}
@Value.Lazy
public GlobHandler getGlobHandler() {
return getDelegate()
.getEnum("project", "glob_handler", GlobHandler.class)
.orElse(GlobHandler.PYTHON);
}
@Value.Lazy
public WatchmanGlobSanityCheck getWatchmanGlobSanityCheck() {
return getDelegate()
.getEnum("project", "watchman_glob_sanity_check", WatchmanGlobSanityCheck.class)
.orElse(WatchmanGlobSanityCheck.STAT);
}
@Value.Lazy
public Optional<Long> getWatchmanQueryTimeoutMs() {
return getDelegate().getLong("project", "watchman_query_timeout_ms");
}
@Value.Lazy
public boolean getWatchCells() {
return getDelegate().getBooleanValue("project", "watch_cells", true);
}
@Value.Lazy
public WatchmanWatcher.CursorType getWatchmanCursor() {
return getDelegate()
.getEnum("project", "watchman_cursor", WatchmanWatcher.CursorType.class)
.orElse(WatchmanWatcher.CursorType.CLOCK_ID);
}
@Value.Lazy
public boolean getEnableParallelParsing() {
return getDelegate().getBooleanValue("project", "parallel_parsing", true);
}
@Value.Lazy
public int getNumParsingThreads() {
if (!getEnableParallelParsing()) {
return 1;
}
int value =
getDelegate()
.getLong("project", "parsing_threads")
.orElse(NUM_PARSING_THREADS_DEFAULT)
.intValue();
return Math.min(value, getDelegate().getNumThreads());
}
@Value.Lazy
public ApplyDefaultFlavorsMode getDefaultFlavorsMode() {
return getDelegate()
.getEnum("project", "default_flavors_mode", ApplyDefaultFlavorsMode.class)
.orElse(ApplyDefaultFlavorsMode.ENABLED);
}
@Value.Lazy
public ImmutableList<String> getBuildFileImportWhitelist() {
return getDelegate().getListWithoutComments("project", "build_file_import_whitelist");
}
/**
* Returns the path to python interpreter. If python is specified in the 'python_interpreter' key
* of the 'parser' section that is used and an error reported if invalid.
*
* <p>If none has been specified, consult the PythonBuckConfig for an interpreter.
*
* @return The found python interpreter.
*/
@Value.Lazy
public String getPythonInterpreter(Optional<String> configPath, ExecutableFinder exeFinder) {
PythonBuckConfig pyconfig = new PythonBuckConfig(getDelegate(), exeFinder);
if (configPath.isPresent()) {
return pyconfig.getPythonInterpreter(configPath);
}
// Fall back to the Python section configuration
return pyconfig.getPythonInterpreter();
}
@Value.Lazy
public String getPythonInterpreter(ExecutableFinder exeFinder) {
Optional<String> configPath = getDelegate().getValue("parser", "python_interpreter");
return getPythonInterpreter(configPath, exeFinder);
}
/**
* Returns the module search path PYTHONPATH to set for the parser, as specified by the
* 'python_path' key of the 'parser' section.
*
* @return The PYTHONPATH value or an empty string if not set.
*/
@Value.Lazy
public Optional<String> getPythonModuleSearchPath() {
return getDelegate().getValue("parser", "python_path");
}
}