Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 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. |
| 14 | package com.google.devtools.build.lib.syntax; |
| 15 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 16 | import com.google.common.collect.ImmutableList; |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 17 | import java.util.Collections; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 18 | import java.util.List; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 19 | import javax.annotation.Nullable; |
| 20 | |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 21 | /** |
| 22 | * Syntax tree for a Starlark file, such as a Bazel BUILD or .bzl file. |
| 23 | * |
| 24 | * <p>Call {@link #parse} to parse a file. Parser errors are recorded in the syntax tree (see {@link |
| 25 | * #errors}), which may be incomplete. |
| 26 | */ |
| 27 | public final class StarlarkFile extends Node { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 28 | |
brandjon | 990622b | 2017-07-11 19:56:45 +0200 | [diff] [blame] | 29 | private final ImmutableList<Statement> statements; |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 30 | private final FileOptions options; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 31 | private final ImmutableList<Comment> comments; |
adonovan | c743435 | 2020-04-24 09:05:50 -0700 | [diff] [blame] | 32 | final List<SyntaxError> errors; // appended to by Resolver |
Lukacs Berki | f445ea1 | 2015-07-09 07:16:41 +0000 | [diff] [blame] | 33 | |
adonovan | 7350946 | 2020-04-27 15:19:33 -0700 | [diff] [blame] | 34 | // set by resolver |
| 35 | @Nullable Resolver.Function resolved; |
| 36 | |
adonovan | 07b15e6 | 2020-04-09 18:32:33 -0700 | [diff] [blame] | 37 | @Override |
| 38 | public int getStartOffset() { |
| 39 | return 0; |
| 40 | } |
| 41 | |
| 42 | @Override |
| 43 | public int getEndOffset() { |
adonovan | d51ac9b | 2020-04-10 10:15:08 -0700 | [diff] [blame] | 44 | return locs.size(); |
adonovan | 07b15e6 | 2020-04-09 18:32:33 -0700 | [diff] [blame] | 45 | } |
| 46 | |
Googler | 66d099e | 2019-09-26 08:07:06 -0700 | [diff] [blame] | 47 | private StarlarkFile( |
adonovan | d51ac9b | 2020-04-10 10:15:08 -0700 | [diff] [blame] | 48 | FileLocations locs, |
brandjon | 990622b | 2017-07-11 19:56:45 +0200 | [diff] [blame] | 49 | ImmutableList<Statement> statements, |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 50 | FileOptions options, |
| 51 | ImmutableList<Comment> comments, |
adonovan | 4a99774 | 2020-05-08 05:45:27 -0700 | [diff] [blame] | 52 | List<SyntaxError> errors) { |
adonovan | d51ac9b | 2020-04-10 10:15:08 -0700 | [diff] [blame] | 53 | super(locs); |
brandjon | 990622b | 2017-07-11 19:56:45 +0200 | [diff] [blame] | 54 | this.statements = statements; |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 55 | this.options = options; |
Laurent Le Brun | 8c8857d | 2016-08-04 10:22:16 +0000 | [diff] [blame] | 56 | this.comments = comments; |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 57 | this.errors = errors; |
Miguel Alcon Pinto | 927f3b2 | 2016-08-22 14:21:30 +0000 | [diff] [blame] | 58 | } |
| 59 | |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 60 | // Creates a StarlarkFile from the given effective list of statements, |
| 61 | // which may include the prelude. |
Googler | 66d099e | 2019-09-26 08:07:06 -0700 | [diff] [blame] | 62 | private static StarlarkFile create( |
adonovan | d51ac9b | 2020-04-10 10:15:08 -0700 | [diff] [blame] | 63 | FileLocations locs, |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 64 | ImmutableList<Statement> statements, |
| 65 | FileOptions options, |
adonovan | 4a99774 | 2020-05-08 05:45:27 -0700 | [diff] [blame] | 66 | Parser.ParseResult result) { |
adonovan | d51ac9b | 2020-04-10 10:15:08 -0700 | [diff] [blame] | 67 | return new StarlarkFile( |
adonovan | 4a99774 | 2020-05-08 05:45:27 -0700 | [diff] [blame] | 68 | locs, statements, options, ImmutableList.copyOf(result.comments), result.errors); |
Damien Martin-Guillerez | 5e95a46 | 2016-02-05 22:32:08 +0000 | [diff] [blame] | 69 | } |
| 70 | |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 71 | /** Extract a subtree containing only statements from i (included) to j (excluded). */ |
| 72 | public StarlarkFile subTree(int i, int j) { |
adonovan | d51ac9b | 2020-04-10 10:15:08 -0700 | [diff] [blame] | 73 | return new StarlarkFile( |
| 74 | this.locs, |
| 75 | this.statements.subList(i, j), |
| 76 | this.options, |
| 77 | /*comments=*/ ImmutableList.of(), |
adonovan | 4a99774 | 2020-05-08 05:45:27 -0700 | [diff] [blame] | 78 | errors); |
Miguel Alcon Pinto | 927f3b2 | 2016-08-22 14:21:30 +0000 | [diff] [blame] | 79 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 80 | /** |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 81 | * Returns an unmodifiable view of the list of scanner, parser, and (perhaps) resolver errors |
| 82 | * accumulated in this Starlark file. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 83 | */ |
adonovan | ac1c41e | 2020-04-01 14:28:49 -0700 | [diff] [blame] | 84 | public List<SyntaxError> errors() { |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 85 | return Collections.unmodifiableList(errors); |
| 86 | } |
| 87 | |
| 88 | /** Returns errors().isEmpty(). */ |
| 89 | public boolean ok() { |
| 90 | return errors.isEmpty(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 91 | } |
| 92 | |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 93 | /** Returns an (immutable, ordered) list of statements in this BUILD file. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 94 | public ImmutableList<Statement> getStatements() { |
brandjon | 990622b | 2017-07-11 19:56:45 +0200 | [diff] [blame] | 95 | return statements; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 96 | } |
| 97 | |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 98 | /** Returns an (immutable, ordered) list of comments in this BUILD file. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 99 | public ImmutableList<Comment> getComments() { |
| 100 | return comments; |
| 101 | } |
| 102 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 103 | @Override |
| 104 | public String toString() { |
Googler | 66d099e | 2019-09-26 08:07:06 -0700 | [diff] [blame] | 105 | return "<StarlarkFile with " + statements.size() + " statements>"; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | @Override |
Googler | 4ace465 | 2019-09-16 07:47:08 -0700 | [diff] [blame] | 109 | public void accept(NodeVisitor visitor) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 110 | visitor.visit(this); |
| 111 | } |
| 112 | |
| 113 | /** |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 114 | * Parse the specified file, returning its syntax tree with the prelude statements inserted at the |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 115 | * front of its statement list. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 116 | */ |
Googler | 66d099e | 2019-09-26 08:07:06 -0700 | [diff] [blame] | 117 | public static StarlarkFile parseWithPrelude( |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 118 | ParserInput input, List<Statement> prelude, FileOptions options) { |
| 119 | Parser.ParseResult result = Parser.parseFile(input, options); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 120 | |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 121 | ImmutableList.Builder<Statement> stmts = ImmutableList.builder(); |
| 122 | stmts.addAll(prelude); |
| 123 | stmts.addAll(result.statements); |
| 124 | |
adonovan | 4a99774 | 2020-05-08 05:45:27 -0700 | [diff] [blame] | 125 | return create(result.locs, stmts.build(), options, result); |
Miguel Alcon Pinto | 927f3b2 | 2016-08-22 14:21:30 +0000 | [diff] [blame] | 126 | } |
| 127 | |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 128 | /** |
| 129 | * Parse a Starlark file. |
| 130 | * |
| 131 | * <p>A syntax tree is always returned, even in case of error. Errors are recorded in the tree. |
| 132 | * Example usage: |
| 133 | * |
| 134 | * <pre> |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 135 | * StarlarkFile file = StarlarkFile.parse(input, options); |
Googler | f0890f0 | 2019-10-01 07:28:48 -0700 | [diff] [blame] | 136 | * if (!file.ok()) { |
| 137 | * Event.replayEventsOn(handler, file.errors()); |
| 138 | * ... |
| 139 | * } |
| 140 | * </pre> |
| 141 | */ |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 142 | public static StarlarkFile parse(ParserInput input, FileOptions options) { |
| 143 | Parser.ParseResult result = Parser.parseFile(input, options); |
adonovan | 4a99774 | 2020-05-08 05:45:27 -0700 | [diff] [blame] | 144 | return create(result.locs, ImmutableList.copyOf(result.statements), options, result); |
adonovan | 034220a | 2020-03-24 10:11:26 -0700 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | /** Parse a Starlark file with default options. */ |
| 148 | public static StarlarkFile parse(ParserInput input) { |
| 149 | return parse(input, FileOptions.DEFAULT); |
| 150 | } |
| 151 | |
| 152 | /** Returns the options specified when parsing this file. */ |
| 153 | public FileOptions getOptions() { |
| 154 | return options; |
laurentlb | 04b4c66 | 2017-08-07 20:03:40 +0200 | [diff] [blame] | 155 | } |
adonovan | 8329068 | 2020-05-18 09:08:43 -0700 | [diff] [blame] | 156 | |
adonovan | 09d1370 | 2020-05-19 08:26:55 -0700 | [diff] [blame] | 157 | /** Returns the name of this file, as specified to the parser. */ |
| 158 | public String getName() { |
| 159 | return locs.file(); |
| 160 | } |
| 161 | |
adonovan | 8329068 | 2020-05-18 09:08:43 -0700 | [diff] [blame] | 162 | /** A ParseProfiler records the start and end times of parse operations. */ |
| 163 | public interface ParseProfiler { |
| 164 | Object start(String filename); |
| 165 | |
| 166 | void end(Object span); |
| 167 | } |
| 168 | |
| 169 | /** Installs a global hook that will be notified of parse operations. */ |
| 170 | public static void setParseProfiler(@Nullable ParseProfiler p) { |
| 171 | Parser.profiler = p; |
| 172 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 173 | } |