blob: 106b34898055f44c4bbb06ea8a30eb01c948ac53 [file] [log] [blame]
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01001// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.syntax;
15
16import com.google.common.base.Joiner;
17import com.google.common.collect.ImmutableList;
18import com.google.devtools.build.lib.vfs.PathFragment;
19
20import java.util.List;
21
22/**
23 * Syntax node for an import statement.
24 */
25public final class LoadStatement extends Statement {
26
Googlerecb643d2015-02-26 10:22:49 +000027 public static final String PATH_ERROR_MSG = "Path '%s' is not valid. "
28 + "It should either start with a slash or refer to a file in the current directory.";
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029 private final ImmutableList<Ident> symbols;
30 private final PathFragment importPath;
Florian Weikert45deb332015-06-12 13:01:16 +000031 private final String pathString;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032
33 /**
34 * Constructs an import statement.
35 */
36 LoadStatement(String path, List<Ident> symbols) {
37 this.symbols = ImmutableList.copyOf(symbols);
38 this.importPath = new PathFragment(path + ".bzl");
Florian Weikert45deb332015-06-12 13:01:16 +000039 this.pathString = path;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010040 }
41
42 public ImmutableList<Ident> getSymbols() {
43 return symbols;
44 }
45
46 public PathFragment getImportPath() {
47 return importPath;
48 }
49
50 @Override
51 public String toString() {
52 return String.format("load(\"%s\", %s)", importPath, Joiner.on(", ").join(symbols));
53 }
54
55 @Override
56 void exec(Environment env) throws EvalException, InterruptedException {
57 for (Ident i : symbols) {
58 try {
59 if (i.getName().startsWith("_")) {
60 throw new EvalException(getLocation(), "symbol '" + i + "' is private and cannot "
61 + "be imported");
62 }
63 env.importSymbol(getImportPath(), i.getName());
64 } catch (Environment.NoSuchVariableException | Environment.LoadFailedException e) {
65 throw new EvalException(getLocation(), e.getMessage());
66 }
67 }
68 }
69
70 @Override
71 public void accept(SyntaxTreeVisitor visitor) {
72 visitor.visit(this);
73 }
74
75 @Override
76 void validate(ValidationEnvironment env) throws EvalException {
Florian Weikert45deb332015-06-12 13:01:16 +000077 validateLoadPath();
78
Googlerecb643d2015-02-26 10:22:49 +000079 if (!importPath.isAbsolute() && importPath.segmentCount() > 1) {
80 throw new EvalException(getLocation(), String.format(PATH_ERROR_MSG, importPath));
81 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010082 for (Ident symbol : symbols) {
Laurent Le Brun964d8d52015-04-13 12:15:04 +000083 env.declare(symbol.getName(), getLocation());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010084 }
85 }
Florian Weikert45deb332015-06-12 13:01:16 +000086
87 /**
88 * Throws an exception if the path argument to load() does starts with more than one forward
89 * slash ('/')
90 *
91 * @throws EvalException if the path is empty or starts with two forward slashes
92 */
Florian Weikert5269b3d2015-07-10 09:51:43 +000093 public void validateLoadPath() throws EvalException {
Florian Weikert45deb332015-06-12 13:01:16 +000094 String error = null;
95
96 if (pathString.isEmpty()) {
97 error = "Path argument to load() must not be empty";
98 } else if (pathString.startsWith("//")) {
99 error =
100 "First argument of load() is a path, not a label. "
101 + "It should start with a single slash if it is an absolute path.";
102 }
103
104 if (error != null) {
105 throw new EvalException(getLocation(), error);
106 }
107 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100108}