Remove support for the deprecated include() statement in order to be able to separate Skylark from the rest of the code so that Label parsing can be simplified.

This is another go at []: now that the tests were fixed in [] and [] it can be submitted again.

--
MOS_MIGRATED_REVID=103364881
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index 2734e4f..d685dcf 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -23,19 +23,14 @@
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
 import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.packages.CachingPackageLocator;
 import com.google.devtools.build.lib.profiler.Profiler;
 import com.google.devtools.build.lib.profiler.ProfilerTask;
 import com.google.devtools.build.lib.syntax.DictionaryLiteral.DictionaryEntryLiteral;
 import com.google.devtools.build.lib.syntax.IfStatement.ConditionalStatements;
-import com.google.devtools.build.lib.vfs.Path;
-import com.google.devtools.build.lib.vfs.PathFragment;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -64,14 +59,19 @@
     /** The comments from the parsed file. */
     public final List<Comment> comments;
 
+    /** Represents every statement in the file. */
+    public final Location location;
+
     /** Whether the file contained any errors. */
     public final boolean containsErrors;
 
-    public ParseResult(List<Statement> statements, List<Comment> comments, boolean containsErrors) {
+    public ParseResult(List<Statement> statements, List<Comment> comments, Location location,
+        boolean containsErrors) {
       // No need to copy here; when the object is created, the parser instance is just about to go
       // out of scope and be garbage collected.
       this.statements = Preconditions.checkNotNull(statements);
       this.comments = Preconditions.checkNotNull(comments);
+      this.location = location;
       this.containsErrors = containsErrors;
     }
   }
@@ -180,28 +180,23 @@
   private int errorsCount;
   private boolean recoveryMode;  // stop reporting errors until next statement
 
-  private CachingPackageLocator locator;
-
-  private List<PathFragment> includedFiles;
-
-  private Parser(
-      Lexer lexer,
-      EventHandler eventHandler,
-      CachingPackageLocator locator,
-      ParsingMode parsingMode) {
+  private Parser(Lexer lexer, EventHandler eventHandler, ParsingMode parsingMode) {
     this.lexer = lexer;
     this.eventHandler = eventHandler;
     this.parsingMode = parsingMode;
     this.tokens = lexer.getTokens().iterator();
     this.comments = new ArrayList<>();
-    this.locator = locator;
-    this.includedFiles = new ArrayList<>();
-    this.includedFiles.add(lexer.getFilename());
     nextToken();
   }
 
-  private Parser(Lexer lexer, EventHandler eventHandler, CachingPackageLocator locator) {
-    this(lexer, eventHandler, locator, BUILD);
+  private static Location locationFromStatements(Lexer lexer, List<Statement> statements) {
+    if (!statements.isEmpty()) {
+      return lexer.createLocation(
+          statements.get(0).getLocation().getStartOffset(),
+          statements.get(statements.size() - 1).getLocation().getEndOffset());
+    } else {
+      return Location.fromPathFragment(lexer.getFilename());
+    }
   }
 
   /**
@@ -209,12 +204,13 @@
    * encountered during parsing are reported via "reporter".
    */
   public static ParseResult parseFile(
-      Lexer lexer, EventHandler eventHandler, CachingPackageLocator locator, boolean parsePython) {
+      ParserInputSource input, EventHandler eventHandler, boolean parsePython) {
+    Lexer lexer = new Lexer(input, eventHandler, parsePython);
     ParsingMode parsingMode = parsePython ? PYTHON : BUILD;
-    Parser parser = new Parser(lexer, eventHandler, locator, parsingMode);
+    Parser parser = new Parser(lexer, eventHandler, parsingMode);
     List<Statement> statements = parser.parseFileInput();
-    return new ParseResult(
-        statements, parser.comments, parser.errorsCount > 0 || lexer.containsErrors());
+    return new ParseResult(statements, parser.comments, locationFromStatements(lexer, statements),
+        parser.errorsCount > 0 || lexer.containsErrors());
   }
 
   /**
@@ -223,11 +219,11 @@
    * that are not part of the core BUILD language.
    */
   public static ParseResult parseFileForSkylark(
-      Lexer lexer,
+      ParserInputSource input,
       EventHandler eventHandler,
-      CachingPackageLocator locator,
       @Nullable ValidationEnvironment validationEnvironment) {
-    Parser parser = new Parser(lexer, eventHandler, locator, SKYLARK);
+    Lexer lexer = new Lexer(input, eventHandler, false);
+    Parser parser = new Parser(lexer, eventHandler, SKYLARK);
     List<Statement> statements = parser.parseFileInput();
     boolean hasSemanticalErrors = false;
     try {
@@ -241,7 +237,7 @@
       }
       hasSemanticalErrors = true;
     }
-    return new ParseResult(statements, parser.comments,
+    return new ParseResult(statements, parser.comments, locationFromStatements(lexer, statements),
         parser.errorsCount > 0 || lexer.containsErrors() || hasSemanticalErrors);
   }
 
@@ -251,7 +247,8 @@
    * by newline tokens.
    */
   @VisibleForTesting
-  public static Expression parseExpression(Lexer lexer, EventHandler eventHandler) {
+  public static Expression parseExpression(ParserInputSource input, EventHandler eventHandler) {
+    Lexer lexer = new Lexer(input, eventHandler, false);
     Parser parser = new Parser(lexer, eventHandler, null);
     Expression result = parser.parseExpression();
     while (parser.token.kind == TokenKind.NEWLINE) {
@@ -261,10 +258,6 @@
     return result;
   }
 
-  private void addIncludedFiles(List<PathFragment> files) {
-    this.includedFiles.addAll(files);
-  }
-
   private void reportError(Location location, String message) {
     errorsCount++;
     // Limit the number of reported errors to avoid spamming output.
@@ -601,60 +594,6 @@
     return setLocation(new DictionaryEntryLiteral(key, value), start, value);
   }
 
-  private ExpressionStatement mocksubincludeExpression(
-      String labelName, String file, Location location) {
-    List<Argument.Passed> args = new ArrayList<>();
-    args.add(setLocation(new Argument.Positional(
-        new StringLiteral(labelName, '"')), location));
-    args.add(setLocation(new Argument.Positional(
-        new StringLiteral(file, '"')), location));
-    Identifier mockIdent = setLocation(new Identifier("mocksubinclude"), location);
-    Expression funCall = new FuncallExpression(null, mockIdent, args);
-    return setLocation(new ExpressionStatement(funCall), location);
-  }
-
-  // parse a file from an include call
-  private void include(String labelName, List<Statement> list, Location location) {
-    if (locator == null) {
-      return;
-    }
-
-    try {
-      Label label = Label.parseAbsolute(labelName);
-      // Note that this doesn't really work if the label belongs to a different repository, because
-      // there is no guarantee that its RepositoryValue has been evaluated. In an ideal world, we
-      // could put a Skyframe dependency the appropriate PackageLookupValue, but we can't do that
-      // because package loading is not completely Skyframized.
-      Path packagePath = locator.getBuildFileForPackage(label.getPackageIdentifier());
-      if (packagePath == null) {
-        reportError(location, "Package '" + label.getPackageIdentifier() + "' not found");
-        list.add(mocksubincludeExpression(labelName, "", location));
-        return;
-      }
-      Path path = packagePath.getParentDirectory();
-      Path file = path.getRelative(label.getName());
-
-      if (this.includedFiles.contains(file.asFragment())) {
-        reportError(location, "Recursive inclusion of file '" + path + "'");
-        return;
-      }
-      ParserInputSource inputSource = ParserInputSource.create(file);
-
-      // Insert call to the mocksubinclude function to get the dependencies right.
-      list.add(mocksubincludeExpression(labelName, file.toString(), location));
-
-      Lexer lexer = new Lexer(inputSource, eventHandler, parsingMode == PYTHON);
-      Parser parser = new Parser(lexer, eventHandler, locator, parsingMode);
-      parser.addIncludedFiles(this.includedFiles);
-      list.addAll(parser.parseFileInput());
-    } catch (LabelSyntaxException e) {
-      reportError(location, "Invalid label '" + labelName + "'");
-    } catch (IOException e) {
-      reportError(location, "Include of '" + labelName + "' failed: " + e.getMessage());
-      list.add(mocksubincludeExpression(labelName, "", location));
-    }
-  }
-
   /**
    * Parse a String literal value, e.g. "str".
    */
@@ -1084,7 +1023,7 @@
         parseTopLevelStatement(list);
       }
     }
-    Profiler.instance().logSimpleTask(startTime, ProfilerTask.SKYLARK_PARSER, includedFiles);
+    Profiler.instance().logSimpleTask(startTime, ProfilerTask.SKYLARK_PARSER, "");
     return list;
   }
 
@@ -1174,24 +1113,12 @@
   private void parseTopLevelStatement(List<Statement> list) {
     // In Python grammar, there is no "top-level statement" and imports are
     // considered as "small statements". We are a bit stricter than Python here.
-    int start = token.left;
-
     // Check if there is an include
     if (token.kind == TokenKind.IDENTIFIER) {
       Token identToken = token;
       Identifier ident = parseIdent();
 
-      if (ident.getName().equals("include")
-          && token.kind == TokenKind.LPAREN
-          && parsingMode == BUILD) {
-        expect(TokenKind.LPAREN);
-        if (token.kind == TokenKind.STRING) {
-          include((String) token.value, list, lexer.createLocation(start, token.right));
-        }
-        expect(TokenKind.STRING);
-        expect(TokenKind.RPAREN);
-        return;
-      } else if (ident.getName().equals("load") && token.kind == TokenKind.LPAREN) {
+      if (ident.getName().equals("load") && token.kind == TokenKind.LPAREN) {
         expect(TokenKind.LPAREN);
         parseLoad(list);
         return;