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<<a href="#type_CompletionSuggestion">CompletionSuggestion</a>>
"<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<<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>>
"<b>includedElementKinds</b>": <span style="color:#999999">optional</span> List<<a href="#type_ElementKind">ElementKind</a>>
"<b>includedSuggestionRelevanceTags</b>": <span style="color:#999999">optional</span> List<<a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a>>
@@ -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<<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>><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<int></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<<a href="#type_ExistingImport">ExistingImport</a>></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<String></b></dt><dd>
+
+ <p>
+ The list of unique strings in this object.
+ </p>
+ </dd><dt class="field"><b>uris: List<int></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<int></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
*
* {