@@ -22,7 +22,12 @@ import {
2222 FragmentDefinitionNode ,
2323 SelectionSetNode ,
2424 SelectionNode ,
25+ InterfaceTypeDefinitionNode ,
26+ ObjectTypeDefinitionNode ,
27+ EnumTypeDefinitionNode ,
2528 DefinitionNode ,
29+ InputValueDefinitionNode ,
30+ FieldDefinitionNode ,
2631} from 'graphql' ;
2732import { offsetToPosition , Position } from 'graphql-language-service-utils' ;
2833
@@ -37,28 +42,39 @@ const OUTLINEABLE_KINDS = {
3742 FragmentDefinition : true ,
3843 FragmentSpread : true ,
3944 InlineFragment : true ,
45+ ObjectTypeDefinition : true ,
46+ InputObjectTypeDefinition : true ,
47+ InterfaceTypeDefinition : true ,
48+ EnumTypeDefinition : true ,
49+ InputValueDefinition : true ,
50+ FieldDefinition : true ,
4051} ;
4152
42- type OutlineTreeResult = {
43- representativeName : string ;
44- startPosition : Position ;
45- endPosition : Position ;
46- children : SelectionSetNode [ ] | [ ] ;
47- tokenizedText : TextToken [ ] ;
48- } ;
53+ export type OutlineableKinds = keyof typeof OUTLINEABLE_KINDS ;
4954
50- type OutlineTreeConverterType = {
51- [ name : string ] : (
52- node : any ,
53- ) =>
54- | OutlineTreeResult
55- | SelectionSetNode
56- | readonly DefinitionNode [ ]
57- | readonly SelectionNode [ ]
58- | string ;
59- } ;
55+ // type OutlineableNodes = FieldNode | OperationDefinitionNode | DocumentNode | SelectionSetNode | NameNode | FragmentDefinitionNode | FragmentSpreadNode |InlineFragmentNode | ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode
56+
57+ type OutlineTreeResult =
58+ | {
59+ representativeName : string ;
60+ startPosition : Position ;
61+ endPosition : Position ;
62+ children : SelectionSetNode [ ] | [ ] ;
63+ tokenizedText : TextToken [ ] ;
64+ }
65+ | string
66+ | readonly DefinitionNode [ ]
67+ | readonly SelectionNode [ ]
68+ | FieldNode [ ]
69+ | SelectionSetNode ;
70+
71+ type OutlineTreeConverterType = Partial <
72+ {
73+ [ key in OutlineableKinds ] : ( node : any ) => OutlineTreeResult ;
74+ }
75+ > ;
6076
61- export function getOutline ( queryText : string ) : Outline | null | undefined {
77+ export function getOutline ( queryText : string ) : Outline | null {
6278 let ast ;
6379 try {
6480 ast = parse ( queryText ) ;
@@ -69,10 +85,8 @@ export function getOutline(queryText: string): Outline | null | undefined {
6985 const visitorFns = outlineTreeConverter ( queryText ) ;
7086 const outlineTrees = visit ( ast , {
7187 leave ( node ) {
72- if (
73- OUTLINEABLE_KINDS . hasOwnProperty ( node . kind ) &&
74- visitorFns [ node . kind ]
75- ) {
88+ if ( visitorFns !== undefined && node . kind in visitorFns ) {
89+ // @ts -ignore
7690 return visitorFns [ node . kind ] ( node ) ;
7791 }
7892 return null ;
@@ -85,23 +99,22 @@ export function getOutline(queryText: string): Outline | null | undefined {
8599function outlineTreeConverter ( docText : string ) : OutlineTreeConverterType {
86100 // TODO: couldn't find a type that would work for all cases here,
87101 // however the inference is not broken by this at least
88- const meta = ( node : any ) => ( {
89- representativeName : node . name ,
90- startPosition : offsetToPosition ( docText , node . loc . start ) ,
91- endPosition : offsetToPosition ( docText , node . loc . end ) ,
92- kind : node . kind ,
93- children : node . selectionSet || [ ] ,
94- } ) ;
102+ const meta = ( node : any ) => {
103+ return {
104+ representativeName : node . name ,
105+ startPosition : offsetToPosition ( docText , node . loc . start ) ,
106+ endPosition : offsetToPosition ( docText , node . loc . end ) ,
107+ kind : node . kind ,
108+ children : node . selectionSet || node . fields || node . arguments || [ ] ,
109+ } ;
110+ } ;
95111
96112 return {
97113 Field : ( node : FieldNode ) => {
98114 const tokenizedText = node . alias
99- ? [
100- buildToken ( 'plain' , ( node . alias as unknown ) as string ) ,
101- buildToken ( 'plain' , ': ' ) ,
102- ]
115+ ? [ buildToken ( 'plain' , node . alias ) , buildToken ( 'plain' , ': ' ) ]
103116 : [ ] ;
104- tokenizedText . push ( buildToken ( 'plain' , ( node . name as unknown ) as string ) ) ;
117+ tokenizedText . push ( buildToken ( 'plain' , node . name ) ) ;
105118 return { tokenizedText, ...meta ( node ) } ;
106119 } ,
107120 OperationDefinition : ( node : OperationDefinitionNode ) => ( {
@@ -123,24 +136,67 @@ function outlineTreeConverter(docText: string): OutlineTreeConverterType {
123136 tokenizedText : [
124137 buildToken ( 'keyword' , 'fragment' ) ,
125138 buildToken ( 'whitespace' , ' ' ) ,
126- buildToken ( 'class-name' , ( node . name as unknown ) as string ) ,
139+ buildToken ( 'class-name' , node . name ) ,
140+ ] ,
141+ ...meta ( node ) ,
142+ } ) ,
143+ InterfaceTypeDefinition : ( node : InterfaceTypeDefinitionNode ) => ( {
144+ tokenizedText : [
145+ buildToken ( 'keyword' , 'interface' ) ,
146+ buildToken ( 'whitespace' , ' ' ) ,
147+ buildToken ( 'class-name' , node . name ) ,
148+ ] ,
149+ ...meta ( node ) ,
150+ } ) ,
151+ EnumTypeDefinition : ( node : EnumTypeDefinitionNode ) => ( {
152+ tokenizedText : [
153+ buildToken ( 'keyword' , 'enum' ) ,
154+ buildToken ( 'whitespace' , ' ' ) ,
155+ buildToken ( 'class-name' , node . name ) ,
156+ ] ,
157+ ...meta ( node ) ,
158+ } ) ,
159+ ObjectTypeDefinition : ( node : ObjectTypeDefinitionNode ) => ( {
160+ tokenizedText : [
161+ buildToken ( 'keyword' , 'type' ) ,
162+ buildToken ( 'whitespace' , ' ' ) ,
163+ buildToken ( 'class-name' , node . name ) ,
164+ ] ,
165+ ...meta ( node ) ,
166+ } ) ,
167+ InputObjectTypeDefinition : ( node : ObjectTypeDefinitionNode ) => ( {
168+ tokenizedText : [
169+ buildToken ( 'keyword' , 'input' ) ,
170+ buildToken ( 'whitespace' , ' ' ) ,
171+ buildToken ( 'class-name' , node . name ) ,
127172 ] ,
128173 ...meta ( node ) ,
129174 } ) ,
130-
131175 FragmentSpread : ( node : FragmentSpreadNode ) => ( {
132176 tokenizedText : [
133177 buildToken ( 'plain' , '...' ) ,
134- buildToken ( 'class-name' , ( node . name as unknown ) as string ) ,
178+ buildToken ( 'class-name' , node . name ) ,
135179 ] ,
136180 ...meta ( node ) ,
137181 } ) ,
182+ InputValueDefinition : ( node : InputValueDefinitionNode ) => {
183+ return {
184+ tokenizedText : [ buildToken ( 'plain' , node . name ) ] ,
185+ ...meta ( node ) ,
186+ } ;
187+ } ,
188+ FieldDefinition : ( node : FieldDefinitionNode ) => {
189+ return {
190+ tokenizedText : [ buildToken ( 'plain' , node . name ) ] ,
191+ ...meta ( node ) ,
192+ } ;
193+ } ,
138194
139195 InlineFragment : ( node : InlineFragmentNode ) => node . selectionSet ,
140196 } ;
141197}
142198
143- function buildToken ( kind : TokenKind , value : string | undefined ) : TextToken {
199+ function buildToken ( kind : TokenKind , value : string | NameNode ) : TextToken {
144200 return { kind, value } ;
145201}
146202
0 commit comments