blob: da3430a4d9180105c28bda4fe71f89ade7c57a86 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
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;
Florian Weikert9d659ad2015-07-23 14:44:36 +000018import com.google.common.collect.ImmutableMap;
Florian Weikert9d659ad2015-07-23 14:44:36 +000019import java.util.Map;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010020
21/**
22 * Syntax node for an import statement.
23 */
24public final class LoadStatement extends Statement {
25
brandjon540aac62017-06-12 23:08:09 +020026 private final ImmutableMap<Identifier, String> symbolMap;
Florian Weikert9d659ad2015-07-23 14:44:36 +000027 private final ImmutableList<Identifier> cachedSymbols; // to save time
Laurent Le Brun7b1708c2016-10-13 10:05:12 +000028 private final StringLiteral imp;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029
30 /**
31 * Constructs an import statement.
Florian Weikert9d659ad2015-07-23 14:44:36 +000032 *
John Fielda97e17f2015-11-13 02:19:52 +000033 * <p>{@code symbols} maps a symbol to the original name under which it was defined in
34 * the bzl file that should be loaded. If aliasing is used, the value differs from its key's
35 * {@code symbol.getName()}. Otherwise, both values are identical.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010036 */
brandjon540aac62017-06-12 23:08:09 +020037 public LoadStatement(StringLiteral imp, Map<Identifier, String> symbolMap) {
John Field1ea7fc32015-12-22 19:37:19 +000038 this.imp = imp;
brandjon540aac62017-06-12 23:08:09 +020039 this.symbolMap = ImmutableMap.copyOf(symbolMap);
40 this.cachedSymbols = ImmutableList.copyOf(symbolMap.keySet());
41 }
42
43 public ImmutableMap<Identifier, String> getSymbolMap() {
44 return symbolMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010045 }
46
Florian Weikert6f864c32015-07-23 11:26:39 +000047 public ImmutableList<Identifier> getSymbols() {
Florian Weikert9d659ad2015-07-23 14:44:36 +000048 return cachedSymbols;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010049 }
50
Laurent Le Brun7b1708c2016-10-13 10:05:12 +000051 public StringLiteral getImport() {
John Field1ea7fc32015-12-22 19:37:19 +000052 return imp;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053 }
54
55 @Override
56 public String toString() {
John Field1ea7fc32015-12-22 19:37:19 +000057 return String.format(
Laurent Le Brun7b1708c2016-10-13 10:05:12 +000058 "load(\"%s\", %s)", imp.getValue(), Joiner.on(", ").join(cachedSymbols));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059 }
60
61 @Override
Florian Weikert90a15962015-09-11 13:43:10 +000062 void doExec(Environment env) throws EvalException, InterruptedException {
laurentlbba69b392017-06-14 15:32:41 +020063 if (env.getSemantics().incompatibleLoadArgumentIsLabel) {
64 String s = imp.getValue();
65 if (!s.startsWith("//") && !s.startsWith(":")) {
66 throw new EvalException(
67 getLocation(),
68 "First argument of 'load' must be a label and start with either '//' or ':'. "
brandjonf5b8d6f2017-06-23 18:03:28 +020069 + "Use --incompatibleLoadArgumentIsLabel=false to temporarily disable this check.");
laurentlbba69b392017-06-14 15:32:41 +020070 }
71 }
72
brandjon540aac62017-06-12 23:08:09 +020073 for (Map.Entry<Identifier, String> entry : symbolMap.entrySet()) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010074 try {
Jon Brandveinee8b7aa2016-07-28 15:01:26 +000075 Identifier name = entry.getKey();
76 Identifier declared = new Identifier(entry.getValue());
Florian Weikert9d659ad2015-07-23 14:44:36 +000077
Jon Brandveinee8b7aa2016-07-28 15:01:26 +000078 if (declared.isPrivate()) {
79 throw new EvalException(getLocation(),
80 "symbol '" + declared.getName() + "' is private and cannot be imported.");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010081 }
Florian Weikert9d659ad2015-07-23 14:44:36 +000082 // The key is the original name that was used to define the symbol
John Fielda97e17f2015-11-13 02:19:52 +000083 // in the loaded bzl file.
Laurent Le Brun7b1708c2016-10-13 10:05:12 +000084 env.importSymbol(imp.getValue(), name, declared.getName());
Vladimir Moskva4994cb32016-08-10 15:44:31 +000085 } catch (Environment.LoadFailedException e) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010086 throw new EvalException(getLocation(), e.getMessage());
87 }
88 }
89 }
90
91 @Override
92 public void accept(SyntaxTreeVisitor visitor) {
93 visitor.visit(this);
94 }
95
96 @Override
97 void validate(ValidationEnvironment env) throws EvalException {
Florian Weikert9d659ad2015-07-23 14:44:36 +000098 for (Identifier symbol : cachedSymbols) {
Laurent Le Brun964d8d52015-04-13 12:15:04 +000099 env.declare(symbol.getName(), getLocation());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100100 }
101 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100102}