Add information about existing imports to completion response.

This adds quite a lot of information though, because we send many
strings.

Before: 20686 characters.
After:  55345 characters.

Theoretically we could do better, and send information about existing
imports only once as well, so when the user continues typing in a
single file, without touching imports, we don't send any new data
about imports (maybe just a confirmation that it is still the same).
But I'm not sure if this is a worthwhile optimization.

Actually, even included suggestion sets have similar property - they
don't change for a given file, unless there are changes to other
libraries which we might want to include.

R=brianwilkerson@google.com

Change-Id: I2f55e2dc85508849146aa39eb279beabaec937c0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103561
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index e82eb2b..c10faf7 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.26.1
+  1.27.0
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1455,6 +1455,7 @@
   
   
   
+  
 <h3>Requests</h3><dl><dt class="request"><a name="request_completion.getSuggestions">completion.getSuggestions</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "completion.getSuggestions"
@@ -1612,6 +1613,7 @@
     "<b>replacementLength</b>": int
     "<b>results</b>": List&lt;<a href="#type_CompletionSuggestion">CompletionSuggestion</a>&gt;
     "<b>isLast</b>": bool
+    "<b>libraryFile</b>": <span style="color:#999999">optional</span> <a href="#type_FilePath">FilePath</a>
     "<b>includedSuggestionSets</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;
     "<b>includedElementKinds</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_ElementKind">ElementKind</a>&gt;
     "<b>includedSuggestionRelevanceTags</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a>&gt;
@@ -1663,6 +1665,16 @@
           True if this is that last set of results that will be
           returned for the indicated completion.
         </p>
+      </dd><dt class="field"><b>libraryFile: <a href="#type_FilePath">FilePath</a><span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          The library file that contains the file where completion was
+          requested. The client might use it for example together with the
+          <tt>existingImports</tt> notification to filter out available
+          suggestions. If there were changes to existing imports in the library,
+          the corresponding <tt>existingImports</tt> notification will be sent
+          before the completion notification.
+        </p>
       </dd><dt class="field"><b>includedSuggestionSets: List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
@@ -1720,6 +1732,29 @@
         <p>
           A list of library ids that no longer apply.
         </p>
+      </dd></dl></dd><dt class="notification"><a name="notification_completion.existingImports">completion.existingImports</a></dt><dd><div class="box"><pre>notification: {
+  "event": "completion.existingImports"
+  "params": {
+    "<b>file</b>": <a href="#type_FilePath">FilePath</a>
+    "<b>imports</b>": <a href="#type_ExistingImports">ExistingImports</a>
+  }
+}</pre></div>
+    <p>
+      Reports existing imports in a library. This notification may be sent
+      multiple times for a library. When a notification is processed, clients
+      should replace any previous information for the library.
+    </p>
+    
+  <h4>parameters:</h4><dl><dt class="field"><b>file: <a href="#type_FilePath">FilePath</a></b></dt><dd>
+        
+        <p>
+          The defining file of the library.
+        </p>
+      </dd><dt class="field"><b>imports: <a href="#type_ExistingImports">ExistingImports</a></b></dt><dd>
+        
+        <p>
+          The existing imports in the library.
+        </p>
       </dd></dl></dd></dl>
 <h2 class="domain"><a name="domain_search">search domain</a></h2>
   <p>
@@ -2833,6 +2868,9 @@
   
   
   
+  
+  
+  
 <dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
     <p>
       A directive to begin overlaying the contents of a file. The supplied
@@ -3602,7 +3640,40 @@
       domain.
     </p>
     
-  <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
+  <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_ExistingImport">ExistingImport: object</a></dt><dd>
+    <p>
+      Information about an existing import, with elements that it provides.
+    </p>
+    
+  <dl><dt class="field"><b>uri: int</b></dt><dd>
+        
+        <p>
+          The URI of the imported library.
+          It is an index in the <tt>strings</tt> field, in the enclosing
+          <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+        </p>
+      </dd><dt class="field"><b>elements: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The list of indexes of elements, in the enclosing
+          <tt>ExistingImports</tt> object.
+        </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_ExistingImports">ExistingImports: object</a></dt><dd>
+    <p>
+      Information about all existing imports in a library.
+    </p>
+    
+  <dl><dt class="field"><b>elements: <a href="#type_ImportedElementSet">ImportedElementSet</a></b></dt><dd>
+        
+        <p>
+          The set of all unique imported elements for all imports.
+        </p>
+      </dd><dt class="field"><b>imports: List&lt;<a href="#type_ExistingImport">ExistingImport</a>&gt;</b></dt><dd>
+        
+        <p>
+          The list of imports in the library.
+        </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
     <p>
       An enumeration of the kinds of files.
     </p>
@@ -3944,6 +4015,30 @@
         <p>
           The length of the name of the implemented member.
         </p>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElementSet">ImportedElementSet: object</a></dt><dd>
+    <p>
+      The set of top-level elements encoded as pairs of the defining library
+      URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+      and <tt>elementNames</tt>.
+    </p>
+    
+  <dl><dt class="field"><b>strings: List&lt;String&gt;</b></dt><dd>
+        
+        <p>
+          The list of unique strings in this object.
+        </p>
+      </dd><dt class="field"><b>uris: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The library URI part of the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </dd><dt class="field"><b>names: List&lt;int&gt;</b></dt><dd>
+        
+        <p>
+          The name part of a the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
       </dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElements">ImportedElements: object</a></dt><dd>
     <p>
       A description of the elements that are referenced in a region of a file
@@ -5429,7 +5524,7 @@
   TODO: TBD
 </p>
 <h2 class="domain"><a name="index">Index</a></h2>
-<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
+<h3>Domains</h3><h4>server (<a href="#domain_server">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_server.getVersion">getVersion</a></li><li><a href="#request_server.shutdown">shutdown</a></li><li><a href="#request_server.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_server.connected">connected</a></li><li><a href="#notification_server.error">error</a></li><li><a href="#notification_server.status">status</a></li></ul></div></div><h4>analysis (<a href="#domain_analysis">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_analysis.getErrors">getErrors</a></li><li><a href="#request_analysis.getHover">getHover</a></li><li><a href="#request_analysis.getLibraryDependencies">getLibraryDependencies</a></li><li><a href="#request_analysis.getNavigation">getNavigation</a></li><li><a href="#request_analysis.getReachableSources">getReachableSources</a></li><li><a href="#request_analysis.reanalyze">reanalyze</a></li><li><a href="#request_analysis.setAnalysisRoots">setAnalysisRoots</a></li><li><a href="#request_analysis.setGeneralSubscriptions">setGeneralSubscriptions</a></li><li><a href="#request_analysis.setPriorityFiles">setPriorityFiles</a></li><li><a href="#request_analysis.setSubscriptions">setSubscriptions</a></li><li><a href="#request_analysis.updateContent">updateContent</a></li><li><a href="#request_analysis.updateOptions">updateOptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_analysis.analyzedFiles">analyzedFiles</a></li><li><a href="#notification_analysis.closingLabels">closingLabels</a></li><li><a href="#notification_analysis.errors">errors</a></li><li><a href="#notification_analysis.flushResults">flushResults</a></li><li><a href="#notification_analysis.folding">folding</a></li><li><a href="#notification_analysis.highlights">highlights</a></li><li><a href="#notification_analysis.implemented">implemented</a></li><li><a href="#notification_analysis.invalidate">invalidate</a></li><li><a href="#notification_analysis.navigation">navigation</a></li><li><a href="#notification_analysis.occurrences">occurrences</a></li><li><a href="#notification_analysis.outline">outline</a></li><li><a href="#notification_analysis.overrides">overrides</a></li></ul></div></div><h4>completion (<a href="#domain_completion">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_completion.getSuggestions">getSuggestions</a></li><li><a href="#request_completion.setSubscriptions">setSubscriptions</a></li><li><a href="#request_completion.registerLibraryPaths">registerLibraryPaths</a></li><li><a href="#request_completion.getSuggestionDetails">getSuggestionDetails</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</a></li><li><a href="#notification_completion.availableSuggestions">availableSuggestions</a></li><li><a href="#notification_completion.existingImports">existingImports</a></li></ul></div></div><h4>search (<a href="#domain_search">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_search.findElementReferences">findElementReferences</a></li><li><a href="#request_search.findMemberDeclarations">findMemberDeclarations</a></li><li><a href="#request_search.findMemberReferences">findMemberReferences</a></li><li><a href="#request_search.findTopLevelDeclarations">findTopLevelDeclarations</a></li><li><a href="#request_search.getTypeHierarchy">getTypeHierarchy</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_search.results">results</a></li></ul></div></div><h4>edit (<a href="#domain_edit">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_edit.format">format</a></li><li><a href="#request_edit.getAssists">getAssists</a></li><li><a href="#request_edit.getAvailableRefactorings">getAvailableRefactorings</a></li><li><a href="#request_edit.getFixes">getFixes</a></li><li><a href="#request_edit.getRefactoring">getRefactoring</a></li><li><a href="#request_edit.sortMembers">sortMembers</a></li><li><a href="#request_edit.organizeDirectives">organizeDirectives</a></li></ul></div><h4>execution (<a href="#domain_execution">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_execution.createContext">createContext</a></li><li><a href="#request_execution.deleteContext">deleteContext</a></li><li><a href="#request_execution.getSuggestions">getSuggestions</a></li><li><a href="#request_execution.mapUri">mapUri</a></li><li><a href="#request_execution.setSubscriptions">setSubscriptions</a></li></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_execution.launchData">launchData</a></li></ul></div></div><h4>diagnostic (<a href="#domain_diagnostic">↑</a>)</h4><div class="subindex"><h5>Requests</h5><ul><li><a href="#request_diagnostic.getDiagnostics">getDiagnostics</a></li><li><a href="#request_diagnostic.getServerPort">getServerPort</a></li></ul></div><h3>Types (<a href="#types">↑</a>)</h3><div class="subindex"><ul><li><a href="#type_AddContentOverlay">AddContentOverlay</a></li><li><a href="#type_AnalysisError">AnalysisError</a></li><li><a href="#type_AnalysisErrorFixes">AnalysisErrorFixes</a></li><li><a href="#type_AnalysisErrorSeverity">AnalysisErrorSeverity</a></li><li><a href="#type_AnalysisErrorType">AnalysisErrorType</a></li><li><a href="#type_AnalysisOptions">AnalysisOptions</a></li><li><a href="#type_AnalysisService">AnalysisService</a></li><li><a href="#type_AnalysisStatus">AnalysisStatus</a></li><li><a href="#type_AvailableSuggestion">AvailableSuggestion</a></li><li><a href="#type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</a></li><li><a href="#type_AvailableSuggestionSet">AvailableSuggestionSet</a></li><li><a href="#type_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</a></li><li><a href="#type_CompletionService">CompletionService</a></li><li><a href="#type_CompletionSuggestion">CompletionSuggestion</a></li><li><a href="#type_CompletionSuggestionKind">CompletionSuggestionKind</a></li><li><a href="#type_ContextData">ContextData</a></li><li><a href="#type_DiagnosticMessage">DiagnosticMessage</a></li><li><a href="#type_Element">Element</a></li><li><a href="#type_ElementDeclaration">ElementDeclaration</a></li><li><a href="#type_ElementKind">ElementKind</a></li><li><a href="#type_ExecutableFile">ExecutableFile</a></li><li><a href="#type_ExecutableKind">ExecutableKind</a></li><li><a href="#type_ExecutionContextId">ExecutionContextId</a></li><li><a href="#type_ExecutionService">ExecutionService</a></li><li><a href="#type_ExistingImport">ExistingImport</a></li><li><a href="#type_ExistingImports">ExistingImports</a></li><li><a href="#type_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</a></li><li><a href="#type_FoldingKind">FoldingKind</a></li><li><a href="#type_FoldingRegion">FoldingRegion</a></li><li><a href="#type_GeneralAnalysisService">GeneralAnalysisService</a></li><li><a href="#type_HighlightRegion">HighlightRegion</a></li><li><a href="#type_HighlightRegionType">HighlightRegionType</a></li><li><a href="#type_HoverInformation">HoverInformation</a></li><li><a href="#type_ImplementedClass">ImplementedClass</a></li><li><a href="#type_ImplementedMember">ImplementedMember</a></li><li><a href="#type_ImportedElementSet">ImportedElementSet</a></li><li><a href="#type_ImportedElements">ImportedElements</a></li><li><a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a></li><li><a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a></li><li><a href="#type_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</a></li><li><a href="#type_LibraryPathSet">LibraryPathSet</a></li><li><a href="#type_LinkedEditGroup">LinkedEditGroup</a></li><li><a href="#type_LinkedEditSuggestion">LinkedEditSuggestion</a></li><li><a href="#type_LinkedEditSuggestionKind">LinkedEditSuggestionKind</a></li><li><a href="#type_Location">Location</a></li><li><a href="#type_NavigationRegion">NavigationRegion</a></li><li><a href="#type_NavigationTarget">NavigationTarget</a></li><li><a href="#type_Occurrences">Occurrences</a></li><li><a href="#type_Outline">Outline</a></li><li><a href="#type_OverriddenMember">OverriddenMember</a></li><li><a href="#type_Override">Override</a></li><li><a href="#type_Position">Position</a></li><li><a href="#type_PostfixTemplateDescriptor">PostfixTemplateDescriptor</a></li><li><a href="#type_PubStatus">PubStatus</a></li><li><a href="#type_RefactoringFeedback">RefactoringFeedback</a></li><li><a href="#type_RefactoringKind">RefactoringKind</a></li><li><a href="#type_RefactoringMethodParameter">RefactoringMethodParameter</a></li><li><a href="#type_RefactoringMethodParameterKind">RefactoringMethodParameterKind</a></li><li><a href="#type_RefactoringOptions">RefactoringOptions</a></li><li><a href="#type_RefactoringProblem">RefactoringProblem</a></li><li><a href="#type_RefactoringProblemSeverity">RefactoringProblemSeverity</a></li><li><a href="#type_RemoveContentOverlay">RemoveContentOverlay</a></li><li><a href="#type_RequestError">RequestError</a></li><li><a href="#type_RequestErrorCode">RequestErrorCode</a></li><li><a href="#type_RuntimeCompletionExpression">RuntimeCompletionExpression</a></li><li><a href="#type_RuntimeCompletionExpressionType">RuntimeCompletionExpressionType</a></li><li><a href="#type_RuntimeCompletionExpressionTypeKind">RuntimeCompletionExpressionTypeKind</a></li><li><a href="#type_RuntimeCompletionVariable">RuntimeCompletionVariable</a></li><li><a href="#type_SearchId">SearchId</a></li><li><a href="#type_SearchResult">SearchResult</a></li><li><a href="#type_SearchResultKind">SearchResultKind</a></li><li><a href="#type_ServerService">ServerService</a></li><li><a href="#type_SourceChange">SourceChange</a></li><li><a href="#type_SourceEdit">SourceEdit</a></li><li><a href="#type_SourceFileEdit">SourceFileEdit</a></li><li><a href="#type_TypeHierarchyItem">TypeHierarchyItem</a></li></ul></div><h3>Refactorings (<a href="#refactorings">↑</a>)</h3><div class="subindex"><ul><li><a href="#refactoring_CONVERT_GETTER_TO_METHOD">CONVERT_GETTER_TO_METHOD</a></li><li><a href="#refactoring_CONVERT_METHOD_TO_GETTER">CONVERT_METHOD_TO_GETTER</a></li><li><a href="#refactoring_EXTRACT_LOCAL_VARIABLE">EXTRACT_LOCAL_VARIABLE</a></li><li><a href="#refactoring_EXTRACT_METHOD">EXTRACT_METHOD</a></li><li><a href="#refactoring_EXTRACT_WIDGET">EXTRACT_WIDGET</a></li><li><a href="#refactoring_INLINE_LOCAL_VARIABLE">INLINE_LOCAL_VARIABLE</a></li><li><a href="#refactoring_INLINE_METHOD">INLINE_METHOD</a></li><li><a href="#refactoring_MOVE_FILE">MOVE_FILE</a></li><li><a href="#refactoring_RENAME">RENAME</a></li></ul></div>
 
 
 </body></html>
\ No newline at end of file
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index af958c9..b944f0f 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.26.1';
+const String PROTOCOL_VERSION = '1.27.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
     'changedLibraries';
 const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
     'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+    'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
     'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 287fcd5..bc2c256 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -5803,6 +5803,116 @@
 }
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+  String _file;
+
+  ExistingImports _imports;
+
+  /**
+   * The defining file of the library.
+   */
+  String get file => _file;
+
+  /**
+   * The defining file of the library.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The existing imports in the library.
+   */
+  ExistingImports get imports => _imports;
+
+  /**
+   * The existing imports in the library.
+   */
+  void set imports(ExistingImports value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  CompletionExistingImportsParams(String file, ExistingImports imports) {
+    this.file = file;
+    this.imports = imports;
+  }
+
+  factory CompletionExistingImportsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      ExistingImports imports;
+      if (json.containsKey("imports")) {
+        imports = new ExistingImports.fromJson(
+            jsonDecoder, jsonPath + ".imports", json["imports"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new CompletionExistingImportsParams(file, imports);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.existingImports params", json);
+    }
+  }
+
+  factory CompletionExistingImportsParams.fromNotification(
+      Notification notification) {
+    return new CompletionExistingImportsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["imports"] = imports.toJson();
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.existingImports", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionExistingImportsParams) {
+      return file == other.file && imports == other.imports;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -6593,6 +6703,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6722,8 @@
 
   bool _isLast;
 
+  String _libraryFile;
+
   List<IncludedSuggestionSet> _includedSuggestionSets;
 
   List<ElementKind> _includedElementKinds;
@@ -6703,6 +6816,26 @@
   }
 
   /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  String get libraryFile => _libraryFile;
+
+  /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  void set libraryFile(String value) {
+    this._libraryFile = value;
+  }
+
+  /**
    * References to AvailableSuggestionSet objects previously sent to the
    * client. The client can include applicable names from the referenced
    * library in code completion suggestions.
@@ -6765,7 +6898,8 @@
 
   CompletionResultsParams(String id, int replacementOffset,
       int replacementLength, List<CompletionSuggestion> results, bool isLast,
-      {List<IncludedSuggestionSet> includedSuggestionSets,
+      {String libraryFile,
+      List<IncludedSuggestionSet> includedSuggestionSets,
       List<ElementKind> includedElementKinds,
       List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
@@ -6773,6 +6907,7 @@
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.libraryFile = libraryFile;
     this.includedSuggestionSets = includedSuggestionSets;
     this.includedElementKinds = includedElementKinds;
     this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6955,11 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      String libraryFile;
+      if (json.containsKey("libraryFile")) {
+        libraryFile = jsonDecoder.decodeString(
+            jsonPath + ".libraryFile", json["libraryFile"]);
+      }
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (json.containsKey("includedSuggestionSets")) {
         includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +6988,7 @@
       }
       return new CompletionResultsParams(
           id, replacementOffset, replacementLength, results, isLast,
+          libraryFile: libraryFile,
           includedSuggestionSets: includedSuggestionSets,
           includedElementKinds: includedElementKinds,
           includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7011,9 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (libraryFile != null) {
+      result["libraryFile"] = libraryFile;
+    }
     if (includedSuggestionSets != null) {
       result["includedSuggestionSets"] = includedSuggestionSets
           .map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7049,7 @@
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
           isLast == other.isLast &&
+          libraryFile == other.libraryFile &&
           listEqual(includedSuggestionSets, other.includedSuggestionSets,
               (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
           listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7072,7 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
     hash =
@@ -13011,6 +13157,214 @@
 }
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+  int _uri;
+
+  List<int> _elements;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  int get uri => _uri;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  void set uri(int value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  List<int> get elements => _elements;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  void set elements(List<int> value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  ExistingImport(int uri, List<int> elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  factory ExistingImport.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<int> elements;
+      if (json.containsKey("elements")) {
+        elements = jsonDecoder.decodeList(
+            jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      return new ExistingImport(uri, elements);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["uri"] = uri;
+    result["elements"] = elements;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImport) {
+      return uri == other.uri &&
+          listEqual(elements, other.elements, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+  ImportedElementSet _elements;
+
+  List<ExistingImport> _imports;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  ImportedElementSet get elements => _elements;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  void set elements(ImportedElementSet value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  List<ExistingImport> get imports => _imports;
+
+  /**
+   * The list of imports in the library.
+   */
+  void set imports(List<ExistingImport> value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  factory ExistingImports.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      ImportedElementSet elements;
+      if (json.containsKey("elements")) {
+        elements = new ImportedElementSet.fromJson(
+            jsonDecoder, jsonPath + ".elements", json["elements"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      List<ExistingImport> imports;
+      if (json.containsKey("imports")) {
+        imports = jsonDecoder.decodeList(
+            jsonPath + ".imports",
+            json["imports"],
+            (String jsonPath, Object json) =>
+                new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new ExistingImports(elements, imports);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["elements"] = elements.toJson();
+    result["imports"] =
+        imports.map((ExistingImport value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImports) {
+      return elements == other.elements &&
+          listEqual(imports, other.imports,
+              (ExistingImport a, ExistingImport b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * extractLocalVariable feedback
  *
  * {
@@ -16109,6 +16463,135 @@
 }
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+  List<String> _strings;
+
+  List<int> _uris;
+
+  List<int> _names;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  List<String> get strings => _strings;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  void set strings(List<String> value) {
+    assert(value != null);
+    this._strings = value;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  List<int> get uris => _uris;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  void set uris(List<int> value) {
+    assert(value != null);
+    this._uris = value;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  List<int> get names => _names;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  void set names(List<int> value) {
+    assert(value != null);
+    this._names = value;
+  }
+
+  ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  factory ImportedElementSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<String> strings;
+      if (json.containsKey("strings")) {
+        strings = jsonDecoder.decodeList(
+            jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "strings");
+      }
+      List<int> uris;
+      if (json.containsKey("uris")) {
+        uris = jsonDecoder.decodeList(
+            jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uris");
+      }
+      List<int> names;
+      if (json.containsKey("names")) {
+        names = jsonDecoder.decodeList(
+            jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "names");
+      }
+      return new ImportedElementSet(strings, uris, names);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["strings"] = strings;
+    result["uris"] = uris;
+    result["names"] = names;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ImportedElementSet) {
+      return listEqual(
+              strings, other.strings, (String a, String b) => a == b) &&
+          listEqual(uris, other.uris, (int a, int b) => a == b) &&
+          listEqual(names, other.names, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+    hash = JenkinsSmiHash.combine(hash, names.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ImportedElements
  *
  * {
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 295d23c..4f91833 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -395,8 +395,13 @@
       includedElementKinds,
       includedSuggestionRelevanceTags,
     ).then((CompletionResult result) {
+      String libraryFile;
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (includedElementKinds != null && resolvedUnit != null) {
+        libraryFile = resolvedUnit.libraryElement.source.fullName;
+        server.sendNotification(
+          createExistingImportsNotification(resolvedUnit),
+        );
         includedSuggestionSets = computeIncludedSetList(
           server.declarationsTracker,
           resolvedUnit,
@@ -412,6 +417,7 @@
         result.replacementOffset,
         result.replacementLength,
         result.suggestions,
+        libraryFile,
         includedSuggestionSets,
         includedElementKinds?.toList(),
         includedSuggestionRelevanceTags,
@@ -450,6 +456,7 @@
     int replacementOffset,
     int replacementLength,
     Iterable<CompletionSuggestion> results,
+    String libraryFile,
     List<IncludedSuggestionSet> includedSuggestionSets,
     List<ElementKind> includedElementKinds,
     List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
@@ -461,6 +468,7 @@
         replacementLength,
         results,
         true,
+        libraryFile: libraryFile,
         includedSuggestionSets: includedSuggestionSets,
         includedElementKinds: includedElementKinds,
         includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index ce8b297..deb1db5 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -4,7 +4,9 @@
 
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
 
 /// Compute which suggestion sets should be included into completion inside
@@ -79,6 +81,78 @@
   ).toNotification();
 }
 
+/// Compute existing imports and elements that they provide.
+protocol.Notification createExistingImportsNotification(
+  ResolvedUnitResult resolvedUnit,
+) {
+  var uniqueStrings = _UniqueImportedStrings();
+  var uniqueElements = _UniqueImportedElements();
+  var existingImports = <protocol.ExistingImport>[];
+
+  var importElementList = resolvedUnit.libraryElement.imports;
+  for (var import in importElementList) {
+    var importedUriStr = '${import.importedLibrary.librarySource.uri}';
+
+    var existingImportElements = <int>[];
+    for (var element in import.namespace.definedNames.values) {
+      if (element.librarySource != null) {
+        var index = uniqueElements.indexOf(uniqueStrings, element);
+        existingImportElements.add(index);
+      }
+    }
+
+    existingImports.add(protocol.ExistingImport(
+      uniqueStrings.indexOf(importedUriStr),
+      existingImportElements,
+    ));
+  }
+
+  return protocol.CompletionExistingImportsParams(
+    resolvedUnit.libraryElement.source.fullName,
+    protocol.ExistingImports(
+      protocol.ImportedElementSet(
+        uniqueStrings.values,
+        uniqueElements.uriList,
+        uniqueElements.nameList,
+      ),
+      existingImports,
+    ),
+  ).toNotification();
+}
+
+/// TODO(dantup): We need to expose this because the Declarations code currently
+/// returns declarations with DeclarationKinds but the DartCompletionManager
+/// gives us a list of "included ElementKinds". Maybe it would be better to expose
+/// includedDeclarationKinds and then just map that list to ElementKinds once in
+/// domain_completion for the original protocol?
+protocol.ElementKind protocolElementKind(DeclarationKind kind) {
+  switch (kind) {
+    case DeclarationKind.CLASS:
+      return protocol.ElementKind.CLASS;
+    case DeclarationKind.CLASS_TYPE_ALIAS:
+      return protocol.ElementKind.CLASS_TYPE_ALIAS;
+    case DeclarationKind.CONSTRUCTOR:
+      return protocol.ElementKind.CONSTRUCTOR;
+    case DeclarationKind.ENUM:
+      return protocol.ElementKind.ENUM;
+    case DeclarationKind.ENUM_CONSTANT:
+      return protocol.ElementKind.ENUM_CONSTANT;
+    case DeclarationKind.FUNCTION:
+      return protocol.ElementKind.FUNCTION;
+    case DeclarationKind.FUNCTION_TYPE_ALIAS:
+      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
+    case DeclarationKind.GETTER:
+      return protocol.ElementKind.GETTER;
+    case DeclarationKind.MIXIN:
+      return protocol.ElementKind.MIXIN;
+    case DeclarationKind.SETTER:
+      return protocol.ElementKind.SETTER;
+    case DeclarationKind.VARIABLE:
+      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
+  }
+  return protocol.ElementKind.UNKNOWN;
+}
+
 /// Computes the best URI to import [what] into the [unit] library.
 String _getRelativeFileUri(ResolvedUnitResult unit, Uri what) {
   if (what.scheme == 'file') {
@@ -173,39 +247,6 @@
   );
 }
 
-// TODO(dantup): We need to expose this because the Declarations code currently
-// returns declarations with DeclarationKinds but the DartCompletionManager
-// gives us a list of "included ElementKinds". Maybe it would be better to expose
-// includedDeclarationKinds and then just map that list to ElementKinds once in
-// domain_completion for the original protocol?
-protocol.ElementKind protocolElementKind(DeclarationKind kind) {
-  switch (kind) {
-    case DeclarationKind.CLASS:
-      return protocol.ElementKind.CLASS;
-    case DeclarationKind.CLASS_TYPE_ALIAS:
-      return protocol.ElementKind.CLASS_TYPE_ALIAS;
-    case DeclarationKind.CONSTRUCTOR:
-      return protocol.ElementKind.CONSTRUCTOR;
-    case DeclarationKind.ENUM:
-      return protocol.ElementKind.ENUM;
-    case DeclarationKind.ENUM_CONSTANT:
-      return protocol.ElementKind.ENUM_CONSTANT;
-    case DeclarationKind.FUNCTION:
-      return protocol.ElementKind.FUNCTION;
-    case DeclarationKind.FUNCTION_TYPE_ALIAS:
-      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
-    case DeclarationKind.GETTER:
-      return protocol.ElementKind.GETTER;
-    case DeclarationKind.MIXIN:
-      return protocol.ElementKind.MIXIN;
-    case DeclarationKind.SETTER:
-      return protocol.ElementKind.SETTER;
-    case DeclarationKind.VARIABLE:
-      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
-  }
-  return protocol.ElementKind.UNKNOWN;
-}
-
 class CompletionLibrariesWorker implements SchedulerWorker {
   final DeclarationsTracker tracker;
 
@@ -277,3 +318,56 @@
     _listener = null;
   }
 }
+
+class _ImportedElement {
+  final int uri;
+  final int name;
+
+  @override
+  final int hashCode;
+
+  _ImportedElement(this.uri, this.name)
+      : hashCode = JenkinsSmiHash.hash2(uri, name);
+
+  @override
+  bool operator ==(other) {
+    return other is _ImportedElement && other.uri == uri && other.name == name;
+  }
+}
+
+class _UniqueImportedElements {
+  final map = <_ImportedElement, int>{};
+
+  List<int> get nameList => map.keys.map((e) => e.name).toList();
+
+  List<int> get uriList => map.keys.map((e) => e.uri).toList();
+
+  int indexOf(_UniqueImportedStrings strings, Element element) {
+    var uriStr = '${element.librarySource.uri}';
+    var wrapper = _ImportedElement(
+      strings.indexOf(uriStr),
+      strings.indexOf(element.name),
+    );
+    var index = map[wrapper];
+    if (index == null) {
+      index = map.length;
+      map[wrapper] = index;
+    }
+    return index;
+  }
+}
+
+class _UniqueImportedStrings {
+  final map = <String, int>{};
+
+  List<String> get values => map.keys.toList();
+
+  int indexOf(String str) {
+    var index = map[str];
+    if (index == null) {
+      index = map.length;
+      map[str] = index;
+    }
+    return index;
+  }
+}
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index 6331b59..6df0629 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -31,6 +31,7 @@
 
 ## completion domain
 - [ ] completion.availableSuggestions
+- [ ] completion.existingImports
 - [ ] completion.getSuggestionDetails
 - [x] completion.getSuggestions
 - [x] completion.listTokenDetails
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index fe67037..65c2ca5 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1219,6 +1219,14 @@
    *   True if this is that last set of results that will be returned for the
    *   indicated completion.
    *
+   * libraryFile: FilePath (optional)
+   *
+   *   The library file that contains the file where completion was requested.
+   *   The client might use it for example together with the existingImports
+   *   notification to filter out available suggestions. If there were changes
+   *   to existing imports in the library, the corresponding existingImports
+   *   notification will be sent before the completion notification.
+   *
    * includedSuggestionSets: List<IncludedSuggestionSet> (optional)
    *
    *   References to AvailableSuggestionSet objects previously sent to the
@@ -1279,6 +1287,29 @@
       _onCompletionAvailableSuggestions;
 
   /**
+   * Reports existing imports in a library. This notification may be sent
+   * multiple times for a library. When a notification is processed, clients
+   * should replace any previous information for the library.
+   *
+   * Parameters
+   *
+   * file: FilePath
+   *
+   *   The defining file of the library.
+   *
+   * imports: ExistingImports
+   *
+   *   The existing imports in the library.
+   */
+  Stream<CompletionExistingImportsParams> onCompletionExistingImports;
+
+  /**
+   * Stream controller for [onCompletionExistingImports].
+   */
+  StreamController<CompletionExistingImportsParams>
+      _onCompletionExistingImports;
+
+  /**
    * Perform a search for references to the element defined or referenced at
    * the given offset in the given file.
    *
@@ -2702,6 +2733,10 @@
         new StreamController<CompletionAvailableSuggestionsParams>(sync: true);
     onCompletionAvailableSuggestions =
         _onCompletionAvailableSuggestions.stream.asBroadcastStream();
+    _onCompletionExistingImports =
+        new StreamController<CompletionExistingImportsParams>(sync: true);
+    onCompletionExistingImports =
+        _onCompletionExistingImports.stream.asBroadcastStream();
     _onSearchResults = new StreamController<SearchResultsParams>(sync: true);
     onSearchResults = _onSearchResults.stream.asBroadcastStream();
     _onExecutionLaunchData =
@@ -2804,6 +2839,12 @@
             new CompletionAvailableSuggestionsParams.fromJson(
                 decoder, 'params', params));
         break;
+      case "completion.existingImports":
+        outOfTestExpect(params, isCompletionExistingImportsParams);
+        _onCompletionExistingImports.add(
+            new CompletionExistingImportsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case "search.results":
         outOfTestExpect(params, isSearchResultsParams);
         _onSearchResults
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 23e34a7..70dc041 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -560,6 +560,29 @@
     new MatchesEnum("ExecutionService", ["LAUNCH_DATA"]);
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ */
+final Matcher isExistingImport = new LazyMatcher(() => new MatchesJsonObject(
+    "ExistingImport", {"uri": isInt, "elements": isListOf(isInt)}));
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ */
+final Matcher isExistingImports = new LazyMatcher(() => new MatchesJsonObject(
+    "ExistingImports",
+    {"elements": isImportedElementSet, "imports": isListOf(isExistingImport)}));
+
+/**
  * FileKind
  *
  * enum {
@@ -948,6 +971,22 @@
     "ImplementedMember", {"offset": isInt, "length": isInt}));
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ */
+final Matcher isImportedElementSet = new LazyMatcher(() =>
+    new MatchesJsonObject("ImportedElementSet", {
+      "strings": isListOf(isString),
+      "uris": isListOf(isInt),
+      "names": isListOf(isInt)
+    }));
+
+/**
  * ImportedElements
  *
  * {
@@ -2192,6 +2231,18 @@
         }));
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ */
+final Matcher isCompletionExistingImportsParams = new LazyMatcher(() =>
+    new MatchesJsonObject("completion.existingImports params",
+        {"file": isFilePath, "imports": isExistingImports}));
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -2288,6 +2339,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -2301,6 +2353,7 @@
           "results": isListOf(isCompletionSuggestion),
           "isLast": isBool
         }, optionalFields: {
+          "libraryFile": isFilePath,
           "includedSuggestionSets": isListOf(isIncludedSuggestionSet),
           "includedElementKinds": isListOf(isElementKind),
           "includedSuggestionRelevanceTags":
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
new file mode 100644
index 0000000..a9055d0
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about an existing import, with elements that it provides.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImport {
+
+  public static final ExistingImport[] EMPTY_ARRAY = new ExistingImport[0];
+
+  public static final List<ExistingImport> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in the enclosing
+   * ExistingImports and its ImportedElementSet object.
+   */
+  private final int uri;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  private final int[] elements;
+
+  /**
+   * Constructor for {@link ExistingImport}.
+   */
+  public ExistingImport(int uri, int[] elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExistingImport) {
+      ExistingImport other = (ExistingImport) obj;
+      return
+        other.uri == uri &&
+        Arrays.equals(other.elements, elements);
+    }
+    return false;
+  }
+
+  public static ExistingImport fromJson(JsonObject jsonObject) {
+    int uri = jsonObject.get("uri").getAsInt();
+    int[] elements = JsonUtilities.decodeIntArray(jsonObject.get("elements").getAsJsonArray());
+    return new ExistingImport(uri, elements);
+  }
+
+  public static List<ExistingImport> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExistingImport> list = new ArrayList<ExistingImport>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  public int[] getElements() {
+    return elements;
+  }
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in the enclosing
+   * ExistingImports and its ImportedElementSet object.
+   */
+  public int getUri() {
+    return uri;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(uri);
+    builder.append(elements);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("uri", uri);
+    JsonArray jsonArrayElements = new JsonArray();
+    for (int elt : elements) {
+      jsonArrayElements.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("elements", jsonArrayElements);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("uri=");
+    builder.append(uri + ", ");
+    builder.append("elements=");
+    builder.append(StringUtils.join(elements, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
new file mode 100644
index 0000000..7473d829
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about all existing imports in a library.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImports {
+
+  public static final ExistingImports[] EMPTY_ARRAY = new ExistingImports[0];
+
+  public static final List<ExistingImports> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  private final ImportedElementSet elements;
+
+  /**
+   * The list of imports in the library.
+   */
+  private final List<ExistingImport> imports;
+
+  /**
+   * Constructor for {@link ExistingImports}.
+   */
+  public ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ExistingImports) {
+      ExistingImports other = (ExistingImports) obj;
+      return
+        ObjectUtilities.equals(other.elements, elements) &&
+        ObjectUtilities.equals(other.imports, imports);
+    }
+    return false;
+  }
+
+  public static ExistingImports fromJson(JsonObject jsonObject) {
+    ImportedElementSet elements = ImportedElementSet.fromJson(jsonObject.get("elements").getAsJsonObject());
+    List<ExistingImport> imports = ExistingImport.fromJsonArray(jsonObject.get("imports").getAsJsonArray());
+    return new ExistingImports(elements, imports);
+  }
+
+  public static List<ExistingImports> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ExistingImports> list = new ArrayList<ExistingImports>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  public ImportedElementSet getElements() {
+    return elements;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  public List<ExistingImport> getImports() {
+    return imports;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(elements);
+    builder.append(imports);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.add("elements", elements.toJson());
+    JsonArray jsonArrayImports = new JsonArray();
+    for (ExistingImport elt : imports) {
+      jsonArrayImports.add(elt.toJson());
+    }
+    jsonObject.add("imports", jsonArrayImports);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("elements=");
+    builder.append(elements + ", ");
+    builder.append("imports=");
+    builder.append(StringUtils.join(imports, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
new file mode 100644
index 0000000..50ca031
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * This file has been automatically generated. Please do not edit it manually.
+ * To regenerate the file, use the script "pkg/analysis_server/tool/spec/generate_files".
+ */
+package org.dartlang.analysis.server.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * The set of top-level elements encoded as pairs of the defining library URI and the name, and
+ * stored in the parallel lists elementUris and elementNames.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ImportedElementSet {
+
+  public static final ImportedElementSet[] EMPTY_ARRAY = new ImportedElementSet[0];
+
+  public static final List<ImportedElementSet> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The list of unique strings in this object.
+   */
+  private final List<String> strings;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  private final int[] uris;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  private final int[] names;
+
+  /**
+   * Constructor for {@link ImportedElementSet}.
+   */
+  public ImportedElementSet(List<String> strings, int[] uris, int[] names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ImportedElementSet) {
+      ImportedElementSet other = (ImportedElementSet) obj;
+      return
+        ObjectUtilities.equals(other.strings, strings) &&
+        Arrays.equals(other.uris, uris) &&
+        Arrays.equals(other.names, names);
+    }
+    return false;
+  }
+
+  public static ImportedElementSet fromJson(JsonObject jsonObject) {
+    List<String> strings = JsonUtilities.decodeStringList(jsonObject.get("strings").getAsJsonArray());
+    int[] uris = JsonUtilities.decodeIntArray(jsonObject.get("uris").getAsJsonArray());
+    int[] names = JsonUtilities.decodeIntArray(jsonObject.get("names").getAsJsonArray());
+    return new ImportedElementSet(strings, uris, names);
+  }
+
+  public static List<ImportedElementSet> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<ImportedElementSet> list = new ArrayList<ImportedElementSet>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  public int[] getNames() {
+    return names;
+  }
+
+  /**
+   * The list of unique strings in this object.
+   */
+  public List<String> getStrings() {
+    return strings;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  public int[] getUris() {
+    return uris;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(strings);
+    builder.append(uris);
+    builder.append(names);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    JsonArray jsonArrayStrings = new JsonArray();
+    for (String elt : strings) {
+      jsonArrayStrings.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("strings", jsonArrayStrings);
+    JsonArray jsonArrayUris = new JsonArray();
+    for (int elt : uris) {
+      jsonArrayUris.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("uris", jsonArrayUris);
+    JsonArray jsonArrayNames = new JsonArray();
+    for (int elt : names) {
+      jsonArrayNames.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("names", jsonArrayNames);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("strings=");
+    builder.append(StringUtils.join(strings, ", ") + ", ");
+    builder.append("uris=");
+    builder.append(StringUtils.join(uris, ", ") + ", ");
+    builder.append("names=");
+    builder.append(StringUtils.join(names, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index f091a4a..2edfc64 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.26.1</version>
+  <version>1.27.0</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1588,6 +1588,17 @@
           returned for the indicated completion.
         </p>
       </field>
+      <field name="libraryFile" optional="true">
+        <ref>FilePath</ref>
+        <p>
+          The library file that contains the file where completion was
+          requested. The client might use it for example together with the
+          <tt>existingImports</tt> notification to filter out available
+          suggestions. If there were changes to existing imports in the library,
+          the corresponding <tt>existingImports</tt> notification will be sent
+          before the completion notification.
+        </p>
+      </field>
       <field name="includedSuggestionSets" optional="true">
         <list>
           <ref>IncludedSuggestionSet</ref>
@@ -1658,6 +1669,27 @@
       </field>
     </params>
   </notification>
+  <notification event="existingImports">
+    <p>
+      Reports existing imports in a library. This notification may be sent
+      multiple times for a library. When a notification is processed, clients
+      should replace any previous information for the library.
+    </p>
+    <params>
+      <field name="file">
+        <ref>FilePath</ref>
+        <p>
+          The defining file of the library.
+        </p>
+      </field>
+      <field name="imports">
+        <ref>ExistingImports</ref>
+        <p>
+          The existing imports in the library.
+        </p>
+      </field>
+    </params>
+  </notification>
 </domain>
 <domain name="search">
   <p>
@@ -3669,6 +3701,86 @@
       </field>
     </object>
   </type>
+  <type name="ExistingImport">
+    <p>
+      Information about an existing import, with elements that it provides.
+    </p>
+    <object>
+      <field name="uri">
+        <ref>int</ref>
+        <p>
+          The URI of the imported library.
+          It is an index in the <tt>strings</tt> field, in the enclosing
+          <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+        </p>
+      </field>
+      <field name="elements">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The list of indexes of elements, in the enclosing
+          <tt>ExistingImports</tt> object.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="ExistingImports">
+    <p>
+      Information about all existing imports in a library.
+    </p>
+    <object>
+      <field name="elements">
+        <ref>ImportedElementSet</ref>
+        <p>
+          The set of all unique imported elements for all imports.
+        </p>
+      </field>
+      <field name="imports">
+        <list>
+          <ref>ExistingImport</ref>
+        </list>
+        <p>
+          The list of imports in the library.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="ImportedElementSet">
+    <p>
+      The set of top-level elements encoded as pairs of the defining library
+      URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+      and <tt>elementNames</tt>.
+    </p>
+    <object>
+      <field name="strings">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          The list of unique strings in this object.
+        </p>
+      </field>
+      <field name="uris">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The library URI part of the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </field>
+      <field name="names">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          The name part of a the element.
+          It is an index in the <tt>strings</tt> field.
+        </p>
+      </field>
+    </object>
+  </type>
   <type name="IncludedSuggestionSet">
     <p>
       A reference to an <tt>AvailableSuggestionSet</tt> noting
diff --git a/pkg/analysis_server_client/lib/handler/notification_handler.dart b/pkg/analysis_server_client/lib/handler/notification_handler.dart
index 97ec840..b85aa31 100644
--- a/pkg/analysis_server_client/lib/handler/notification_handler.dart
+++ b/pkg/analysis_server_client/lib/handler/notification_handler.dart
@@ -72,6 +72,11 @@
             new CompletionAvailableSuggestionsParams.fromJson(
                 decoder, 'params', params));
         break;
+      case COMPLETION_NOTIFICATION_EXISTING_IMPORTS:
+        onCompletionExistingImports(
+            new CompletionExistingImportsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case COMPLETION_NOTIFICATION_RESULTS:
         onCompletionResults(
             new CompletionResultsParams.fromJson(decoder, 'params', params));
@@ -221,6 +226,11 @@
   void onCompletionAvailableSuggestions(
       CompletionAvailableSuggestionsParams params) {}
 
+  /// Reports existing imports in a library. This notification may be sent
+  /// multiple times for a library. When a notification is processed, clients
+  /// should replace any previous information for the library.
+  void onCompletionExistingImports(CompletionExistingImportsParams params) {}
+
   /// Reports the completion suggestions that should be presented
   /// to the user. The set of suggestions included in the
   /// notification is always a complete list that supersedes any
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index af958c9..b944f0f 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.26.1';
+const String PROTOCOL_VERSION = '1.27.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
     'changedLibraries';
 const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
     'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+    'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
 const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
     'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index fc05957..ec76e66 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -5803,6 +5803,116 @@
 }
 
 /**
+ * completion.existingImports params
+ *
+ * {
+ *   "file": FilePath
+ *   "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+  String _file;
+
+  ExistingImports _imports;
+
+  /**
+   * The defining file of the library.
+   */
+  String get file => _file;
+
+  /**
+   * The defining file of the library.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The existing imports in the library.
+   */
+  ExistingImports get imports => _imports;
+
+  /**
+   * The existing imports in the library.
+   */
+  void set imports(ExistingImports value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  CompletionExistingImportsParams(String file, ExistingImports imports) {
+    this.file = file;
+    this.imports = imports;
+  }
+
+  factory CompletionExistingImportsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      ExistingImports imports;
+      if (json.containsKey("imports")) {
+        imports = new ExistingImports.fromJson(
+            jsonDecoder, jsonPath + ".imports", json["imports"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new CompletionExistingImportsParams(file, imports);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.existingImports params", json);
+    }
+  }
+
+  factory CompletionExistingImportsParams.fromNotification(
+      Notification notification) {
+    return new CompletionExistingImportsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["imports"] = imports.toJson();
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.existingImports", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionExistingImportsParams) {
+      return file == other.file && imports == other.imports;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestionDetails params
  *
  * {
@@ -6593,6 +6703,7 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "libraryFile": optional FilePath
  *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
  *   "includedElementKinds": optional List<ElementKind>
  *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6722,8 @@
 
   bool _isLast;
 
+  String _libraryFile;
+
   List<IncludedSuggestionSet> _includedSuggestionSets;
 
   List<ElementKind> _includedElementKinds;
@@ -6703,6 +6816,26 @@
   }
 
   /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  String get libraryFile => _libraryFile;
+
+  /**
+   * The library file that contains the file where completion was requested.
+   * The client might use it for example together with the existingImports
+   * notification to filter out available suggestions. If there were changes to
+   * existing imports in the library, the corresponding existingImports
+   * notification will be sent before the completion notification.
+   */
+  void set libraryFile(String value) {
+    this._libraryFile = value;
+  }
+
+  /**
    * References to AvailableSuggestionSet objects previously sent to the
    * client. The client can include applicable names from the referenced
    * library in code completion suggestions.
@@ -6765,7 +6898,8 @@
 
   CompletionResultsParams(String id, int replacementOffset,
       int replacementLength, List<CompletionSuggestion> results, bool isLast,
-      {List<IncludedSuggestionSet> includedSuggestionSets,
+      {String libraryFile,
+      List<IncludedSuggestionSet> includedSuggestionSets,
       List<ElementKind> includedElementKinds,
       List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
@@ -6773,6 +6907,7 @@
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.libraryFile = libraryFile;
     this.includedSuggestionSets = includedSuggestionSets;
     this.includedElementKinds = includedElementKinds;
     this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6955,11 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      String libraryFile;
+      if (json.containsKey("libraryFile")) {
+        libraryFile = jsonDecoder.decodeString(
+            jsonPath + ".libraryFile", json["libraryFile"]);
+      }
       List<IncludedSuggestionSet> includedSuggestionSets;
       if (json.containsKey("includedSuggestionSets")) {
         includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +6988,7 @@
       }
       return new CompletionResultsParams(
           id, replacementOffset, replacementLength, results, isLast,
+          libraryFile: libraryFile,
           includedSuggestionSets: includedSuggestionSets,
           includedElementKinds: includedElementKinds,
           includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7011,9 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (libraryFile != null) {
+      result["libraryFile"] = libraryFile;
+    }
     if (includedSuggestionSets != null) {
       result["includedSuggestionSets"] = includedSuggestionSets
           .map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7049,7 @@
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
           isLast == other.isLast &&
+          libraryFile == other.libraryFile &&
           listEqual(includedSuggestionSets, other.includedSuggestionSets,
               (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
           listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7072,7 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
     hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
     hash =
@@ -13011,6 +13157,214 @@
 }
 
 /**
+ * ExistingImport
+ *
+ * {
+ *   "uri": int
+ *   "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+  int _uri;
+
+  List<int> _elements;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  int get uri => _uri;
+
+  /**
+   * The URI of the imported library. It is an index in the strings field, in
+   * the enclosing ExistingImports and its ImportedElementSet object.
+   */
+  void set uri(int value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  List<int> get elements => _elements;
+
+  /**
+   * The list of indexes of elements, in the enclosing ExistingImports object.
+   */
+  void set elements(List<int> value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  ExistingImport(int uri, List<int> elements) {
+    this.uri = uri;
+    this.elements = elements;
+  }
+
+  factory ExistingImport.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<int> elements;
+      if (json.containsKey("elements")) {
+        elements = jsonDecoder.decodeList(
+            jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      return new ExistingImport(uri, elements);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["uri"] = uri;
+    result["elements"] = elements;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImport) {
+      return uri == other.uri &&
+          listEqual(elements, other.elements, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ *   "elements": ImportedElementSet
+ *   "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+  ImportedElementSet _elements;
+
+  List<ExistingImport> _imports;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  ImportedElementSet get elements => _elements;
+
+  /**
+   * The set of all unique imported elements for all imports.
+   */
+  void set elements(ImportedElementSet value) {
+    assert(value != null);
+    this._elements = value;
+  }
+
+  /**
+   * The list of imports in the library.
+   */
+  List<ExistingImport> get imports => _imports;
+
+  /**
+   * The list of imports in the library.
+   */
+  void set imports(List<ExistingImport> value) {
+    assert(value != null);
+    this._imports = value;
+  }
+
+  ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+    this.elements = elements;
+    this.imports = imports;
+  }
+
+  factory ExistingImports.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      ImportedElementSet elements;
+      if (json.containsKey("elements")) {
+        elements = new ImportedElementSet.fromJson(
+            jsonDecoder, jsonPath + ".elements", json["elements"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "elements");
+      }
+      List<ExistingImport> imports;
+      if (json.containsKey("imports")) {
+        imports = jsonDecoder.decodeList(
+            jsonPath + ".imports",
+            json["imports"],
+            (String jsonPath, Object json) =>
+                new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "imports");
+      }
+      return new ExistingImports(elements, imports);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["elements"] = elements.toJson();
+    result["imports"] =
+        imports.map((ExistingImport value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ExistingImports) {
+      return elements == other.elements &&
+          listEqual(imports, other.imports,
+              (ExistingImport a, ExistingImport b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+    hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * extractLocalVariable feedback
  *
  * {
@@ -16109,6 +16463,135 @@
 }
 
 /**
+ * ImportedElementSet
+ *
+ * {
+ *   "strings": List<String>
+ *   "uris": List<int>
+ *   "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+  List<String> _strings;
+
+  List<int> _uris;
+
+  List<int> _names;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  List<String> get strings => _strings;
+
+  /**
+   * The list of unique strings in this object.
+   */
+  void set strings(List<String> value) {
+    assert(value != null);
+    this._strings = value;
+  }
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  List<int> get uris => _uris;
+
+  /**
+   * The library URI part of the element. It is an index in the strings field.
+   */
+  void set uris(List<int> value) {
+    assert(value != null);
+    this._uris = value;
+  }
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  List<int> get names => _names;
+
+  /**
+   * The name part of a the element. It is an index in the strings field.
+   */
+  void set names(List<int> value) {
+    assert(value != null);
+    this._names = value;
+  }
+
+  ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+    this.strings = strings;
+    this.uris = uris;
+    this.names = names;
+  }
+
+  factory ImportedElementSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<String> strings;
+      if (json.containsKey("strings")) {
+        strings = jsonDecoder.decodeList(
+            jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "strings");
+      }
+      List<int> uris;
+      if (json.containsKey("uris")) {
+        uris = jsonDecoder.decodeList(
+            jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uris");
+      }
+      List<int> names;
+      if (json.containsKey("names")) {
+        names = jsonDecoder.decodeList(
+            jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "names");
+      }
+      return new ImportedElementSet(strings, uris, names);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["strings"] = strings;
+    result["uris"] = uris;
+    result["names"] = names;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is ImportedElementSet) {
+      return listEqual(
+              strings, other.strings, (String a, String b) => a == b) &&
+          listEqual(uris, other.uris, (int a, int b) => a == b) &&
+          listEqual(names, other.names, (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+    hash = JenkinsSmiHash.combine(hash, names.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ImportedElements
  *
  * {