@@ -11,7 +11,6 @@ import {
1111 DocumentNode ,
1212 FragmentSpreadNode ,
1313 FragmentDefinitionNode ,
14- OperationDefinitionNode ,
1514 TypeDefinitionNode ,
1615 NamedTypeNode ,
1716 ValidationRule ,
@@ -26,10 +25,16 @@ import {
2625 GraphQLProjectConfig ,
2726 Uri ,
2827 Position ,
28+ Outline ,
29+ OutlineTree ,
2930} from 'graphql-language-service-types' ;
3031
3132// import { Position } from 'graphql-language-service-utils';
32- import { Hover , DiagnosticSeverity } from 'vscode-languageserver-types' ;
33+ import {
34+ Hover ,
35+ SymbolInformation ,
36+ SymbolKind ,
37+ } from 'vscode-languageserver-types' ;
3338
3439import { Kind , parse , print } from 'graphql' ;
3540import { getAutocompleteSuggestions } from './getAutocompleteSuggestions' ;
@@ -41,6 +46,8 @@ import {
4146 getDefinitionQueryResultForNamedType ,
4247} from './getDefinition' ;
4348
49+ import { getOutline } from './getOutline' ;
50+
4451import {
4552 getASTNodeAtPosition ,
4653 requireFile ,
@@ -67,6 +74,33 @@ const {
6774 NAMED_TYPE ,
6875} = Kind ;
6976
77+ const KIND_TO_SYMBOL_KIND : { [ key : string ] : SymbolKind } = {
78+ Field : SymbolKind . Field ,
79+ OperationDefinition : SymbolKind . Class ,
80+ FragmentDefinition : SymbolKind . Class ,
81+ FragmentSpread : SymbolKind . Struct ,
82+ ObjectTypeDefinition : SymbolKind . Class ,
83+ EnumTypeDefinition : SymbolKind . Enum ,
84+ EnumValueDefinition : SymbolKind . EnumMember ,
85+ InputObjectTypeDefinition : SymbolKind . Class ,
86+ InputValueDefinition : SymbolKind . Field ,
87+ FieldDefinition : SymbolKind . Field ,
88+ InterfaceTypeDefinition : SymbolKind . Interface ,
89+ Document : SymbolKind . File ,
90+ FieldWithArguments : SymbolKind . Method ,
91+ } ;
92+
93+ function getKind ( tree : OutlineTree ) {
94+ if (
95+ tree . kind === 'FieldDefinition' &&
96+ tree . children &&
97+ tree . children . length > 0
98+ ) {
99+ return KIND_TO_SYMBOL_KIND . FieldWithArguments ;
100+ }
101+ return KIND_TO_SYMBOL_KIND [ tree . kind ] ;
102+ }
103+
70104export class GraphQLLanguageService {
71105 _graphQLCache : GraphQLCache ;
72106 _graphQLConfig : GraphQLConfig ;
@@ -84,7 +118,7 @@ export class GraphQLLanguageService {
84118 throw Error ( `No config found for uri: ${ uri } ` ) ;
85119 }
86120
87- async getDiagnostics (
121+ public async getDiagnostics (
88122 query : string ,
89123 uri : Uri ,
90124 isRelayCompatMode ?: boolean ,
@@ -123,7 +157,7 @@ export class GraphQLLanguageService {
123157 const range = getRange ( error . locations [ 0 ] , query ) ;
124158 return [
125159 {
126- severity : SEVERITY . ERROR as DiagnosticSeverity ,
160+ severity : SEVERITY . ERROR ,
127161 message : error . message ,
128162 source : 'GraphQL: Syntax' ,
129163 range,
@@ -187,7 +221,7 @@ export class GraphQLLanguageService {
187221 return validateQuery ( validationAst , schema , customRules , isRelayCompatMode ) ;
188222 }
189223
190- async getAutocompleteSuggestions (
224+ public async getAutocompleteSuggestions (
191225 query : string ,
192226 position : Position ,
193227 filePath : Uri ,
@@ -203,7 +237,7 @@ export class GraphQLLanguageService {
203237 return [ ] ;
204238 }
205239
206- async getHoverInformation (
240+ public async getHoverInformation (
207241 query : string ,
208242 position : Position ,
209243 filePath : Uri ,
@@ -219,7 +253,7 @@ export class GraphQLLanguageService {
219253 return '' ;
220254 }
221255
222- async getDefinition (
256+ public async getDefinition (
223257 query : string ,
224258 position : Position ,
225259 filePath : Uri ,
@@ -250,7 +284,7 @@ export class GraphQLLanguageService {
250284 return getDefinitionQueryResultForDefinitionNode (
251285 filePath ,
252286 query ,
253- node as FragmentDefinitionNode | OperationDefinitionNode ,
287+ node ,
254288 ) ;
255289
256290 case NAMED_TYPE :
@@ -266,6 +300,55 @@ export class GraphQLLanguageService {
266300 return null ;
267301 }
268302
303+ public async getDocumentSymbols (
304+ document : string ,
305+ filePath : Uri ,
306+ ) : Promise < SymbolInformation [ ] > {
307+ const outline = await this . getOutline ( document ) ;
308+ if ( ! outline ) {
309+ return [ ] ;
310+ }
311+
312+ const output : Array < SymbolInformation > = [ ] ;
313+ const input = outline . outlineTrees . map ( ( tree : OutlineTree ) => [ null , tree ] ) ;
314+
315+ while ( input . length > 0 ) {
316+ const res = input . pop ( ) ;
317+ if ( ! res ) {
318+ return [ ] ;
319+ }
320+ const [ parent , tree ] = res ;
321+ if ( ! tree ) {
322+ return [ ] ;
323+ }
324+
325+ output . push ( {
326+ // @ts -ignore
327+ name : tree . representativeName ,
328+ kind : getKind ( tree ) ,
329+ location : {
330+ uri : filePath ,
331+ range : {
332+ start : tree . startPosition ,
333+ // @ts -ignore
334+ end : tree . endPosition ,
335+ } ,
336+ } ,
337+ containerName : parent ? parent . representativeName : undefined ,
338+ } ) ;
339+ input . push ( ...tree . children . map ( child => [ tree , child ] ) ) ;
340+ }
341+ return output ;
342+ }
343+ //
344+ // public async getReferences(
345+ // document: string,
346+ // position: Position,
347+ // filePath: Uri,
348+ // ): Promise<Location[]> {
349+ //
350+ // }
351+
269352 async _getDefinitionForNamedType (
270353 query : string ,
271354 ast : DocumentNode ,
@@ -287,7 +370,8 @@ export class GraphQLLanguageService {
287370 definition . kind === OBJECT_TYPE_DEFINITION ||
288371 definition . kind === INPUT_OBJECT_TYPE_DEFINITION ||
289372 definition . kind === ENUM_TYPE_DEFINITION ||
290- definition . kind === SCALAR_TYPE_DEFINITION ,
373+ definition . kind === SCALAR_TYPE_DEFINITION ||
374+ definition . kind === INTERFACE_TYPE_DEFINITION ,
291375 ) ;
292376
293377 const typeCastedDefs = ( localObjectTypeDefinitions as any ) as Array <
@@ -351,4 +435,7 @@ export class GraphQLLanguageService {
351435
352436 return result ;
353437 }
438+ async getOutline ( query : string ) : Promise < Outline | null | undefined > {
439+ return getOutline ( query ) ;
440+ }
354441}
0 commit comments