Add an option to use one-phase summaries.

When this flag is enabled, we fail:
  2 language_2/ tests;
  25 Analyzer tests (mostly by 2 reasons);
  0 Analysis Server tests.

There is a know problem: because unlinked summaries don't include
initializers for variables, we fail to recognize API changes related
to inferred types. I will fix this be computing API signatures from
pertinent tokens.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I61734e96ee26b3e04027a103ccf6850695815127
Reviewed-on: https://dart-review.googlesource.com/74700
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 9bdaca9..8e90b2d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/defined_names.dart';
+import 'package:analyzer/src/dart/analysis/one_phase_summaries_selector.dart';
 import 'package:analyzer/src/dart/analysis/referenced_names.dart';
 import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
@@ -386,7 +387,8 @@
    *
    * If an exception happens during parsing, an empty unit is returned.
    */
-  CompilationUnit parse(AnalysisErrorListener errorListener) {
+  CompilationUnit parse([AnalysisErrorListener errorListener]) {
+    errorListener ??= AnalysisErrorListener.NULL_LISTENER;
     try {
       return PerformanceStatistics.parse.makeCurrentWhile(() {
         return _parse(errorListener);
@@ -430,9 +432,10 @@
     {
       bytes = _fsState._byteStore.get(_unlinkedKey);
       if (bytes == null || bytes.isEmpty) {
-        CompilationUnit unit = parse(AnalysisErrorListener.NULL_LISTENER);
+        CompilationUnit unit = parse();
         _fsState._logger.run('Create unlinked for $path', () {
-          UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
+          UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit,
+              serializeInferrableFields: !enableOnePhaseSummaries);
           DefinedNames definedNames = computeDefinedNames(unit);
           List<String> referencedNames = computeReferencedNames(unit).toList();
           List<String> subtypedNames = computeSubtypedNames(unit).toList();
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index a212a8f..559ed4d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -3,11 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
 import 'package:analyzer/dart/element/element.dart'
     show CompilationUnitElement, LibraryElement;
 import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/dart/analysis/one_phase_summaries_selector.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/handle.dart';
 import 'package:analyzer/src/generated/engine.dart'
@@ -16,7 +18,9 @@
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/link.dart';
+import 'package:analyzer/src/summary/one_phase.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
 import 'package:front_end/src/api_prototype/byte_store.dart';
 import 'package:front_end/src/base/performance_logger.dart';
 
@@ -93,7 +97,8 @@
         appendLibraryFiles(targetLibrary);
       });
 
-      Set<String> libraryUrisToLink = new Set<String>();
+      var libraryUrisToLink = new Set<String>();
+      var libraryFilesToLink = new Set<FileState>();
       logger.run('Load linked bundles', () {
         for (FileState library in libraries.values) {
           if (library.exists || library == targetLibrary) {
@@ -104,6 +109,7 @@
               store.addLinkedLibrary(library.uriStr, linked);
             } else {
               libraryUrisToLink.add(library.uriStr);
+              libraryFilesToLink.add(library);
             }
           }
         }
@@ -112,16 +118,47 @@
       });
 
       Map<String, LinkedLibraryBuilder> linkedLibraries = {};
-      logger.run('Link bundles', () {
-        linkedLibraries = link(libraryUrisToLink, (String uri) {
-          LinkedLibrary linkedLibrary = store.linkedMap[uri];
-          return linkedLibrary;
-        }, (String uri) {
-          UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
-          return unlinkedUnit;
-        }, (_) => null);
-        logger.writeln('Linked ${linkedLibraries.length} bundles.');
-      });
+      if (enableOnePhaseSummaries) {
+        var uriToUnit = <String, CompilationUnit>{};
+        logger.run('Parse files', () {
+          for (var library in libraryFilesToLink) {
+            for (var file in library.libraryFiles) {
+              uriToUnit[file.uriStr] = file.parse();
+            }
+          }
+          logger.writeln('Parsed ${uriToUnit.length} files.');
+        });
+
+        logger.run('Link libraries', () {
+          var assembler = new PackageBundleAssembler();
+          summarize(uriToUnit, store, assembler, (_) => null, true);
+
+          var bundle = assembler.assemble();
+          for (int i = 0; i < bundle.linkedLibraryUris.length; i++) {
+            var uri = bundle.linkedLibraryUris[i];
+
+            // TODO(scheglov) At the moment we might get parts here.
+            if (!libraries.containsKey(uri)) {
+              continue;
+            }
+
+            linkedLibraries[uri] = bundle.linkedLibraries[i];
+          }
+
+          logger.writeln('Linked ${linkedLibraries.length} libraries.');
+        });
+      } else {
+        logger.run('Link libraries', () {
+          linkedLibraries = link(libraryUrisToLink, (String uri) {
+            LinkedLibrary linkedLibrary = store.linkedMap[uri];
+            return linkedLibrary;
+          }, (String uri) {
+            UnlinkedUnit unlinkedUnit = store.unlinkedMap[uri];
+            return unlinkedUnit;
+          }, (_) => null);
+          logger.writeln('Linked ${linkedLibraries.length} libraries.');
+        });
+      }
 
       for (String uri in linkedLibraries.keys) {
         LinkedLibraryBuilder linkedBuilder = linkedLibraries[uri];
diff --git a/pkg/analyzer/lib/src/dart/analysis/one_phase_summaries_selector.dart b/pkg/analyzer/lib/src/dart/analysis/one_phase_summaries_selector.dart
new file mode 100644
index 0000000..c172ea1
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/one_phase_summaries_selector.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A flag indicating whether analysis driver should work using one-phase,
+/// unresolved AST based summaries, or using old unlinked / link process.
+const bool enableOnePhaseSummaries =
+    const bool.fromEnvironment('enableOnePhaseSummaries', defaultValue: false);
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index d8db996..ca03d8e 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -909,7 +909,7 @@
     // Notify the driver about the change.
     driver.changeFile(testFile);
 
-    // The file was added, so it is scheduled for analysis.
+    // The file was changed, so it is scheduled for analysis.
     expect(driver.test.fileTracker.isFilePending(testFile), isTrue);
 
     // We get a new result.