@@ -52,15 +52,16 @@ import type {
5252 DocumentSymbolParams ,
5353 SymbolInformation ,
5454 WorkspaceSymbolParams ,
55+ IConnection ,
5556} from 'vscode-languageserver' ;
5657
5758import type { UnnormalizedTypeDefPointer } from '@graphql-tools/load' ;
5859
5960import { getGraphQLCache } from './GraphQLCache' ;
60- import { parseDocument } from './parseDocument' ;
61+ import { parseDocument , DEFAULT_SUPPORTED_EXTENSIONS } from './parseDocument' ;
6162
6263import { Logger } from './Logger' ;
63- import { printSchema } from 'graphql' ;
64+ import { printSchema , visit , parse , FragmentDefinitionNode } from 'graphql' ;
6465import { tmpdir } from 'os' ;
6566import { GraphQLExtensionDeclaration } from 'graphql-config' ;
6667import type { LoadConfigOptions } from './types' ;
@@ -74,6 +75,7 @@ type CachedDocumentType = {
7475} ;
7576
7677export class MessageProcessor {
78+ _connection : IConnection ;
7779 _graphQLCache ! : GraphQLCache ;
7880 _graphQLConfig : GraphQLConfig | undefined ;
7981 _languageService ! : GraphQLLanguageService ;
@@ -88,6 +90,7 @@ export class MessageProcessor {
8890 _tmpDirBase : string ;
8991 _loadConfigOptions : LoadConfigOptions ;
9092 _schemaCacheInit : boolean = false ;
93+ _rootPath : string = process . cwd ( ) ;
9194
9295 constructor ( {
9396 logger,
@@ -97,6 +100,7 @@ export class MessageProcessor {
97100 config,
98101 parser,
99102 tmpDir,
103+ connection,
100104 } : {
101105 logger : Logger ;
102106 fileExtensions : string [ ] ;
@@ -105,7 +109,9 @@ export class MessageProcessor {
105109 config ?: GraphQLConfig ;
106110 parser ?: typeof parseDocument ;
107111 tmpDir ?: string ;
112+ connection : IConnection ;
108113 } ) {
114+ this . _connection = connection ;
109115 this . _textDocumentCache = new Map ( ) ;
110116 this . _isInitialized = false ;
111117 this . _willShutdown = false ;
@@ -130,6 +136,12 @@ export class MessageProcessor {
130136 mkdirp ( this . _tmpDirBase ) ;
131137 }
132138 }
139+ get connection ( ) : IConnection {
140+ return this . _connection ;
141+ }
142+ set connection ( connection : IConnection ) {
143+ this . _connection = connection ;
144+ }
133145
134146 async handleInitializeRequest (
135147 params : InitializeParams ,
@@ -151,15 +163,25 @@ export class MessageProcessor {
151163 definitionProvider : true ,
152164 textDocumentSync : 1 ,
153165 hoverProvider : true ,
166+ workspace : {
167+ workspaceFolders : {
168+ supported : true ,
169+ changeNotifications : true ,
170+ } ,
171+ } ,
154172 } ,
155173 } ;
156174
157- const rootPath = configDir ? configDir . trim ( ) : params . rootPath ;
158- if ( ! rootPath ) {
159- throw new Error (
160- '`--configDir` option or `rootPath` argument is required.' ,
175+ this . _rootPath = configDir
176+ ? configDir . trim ( )
177+ : params . rootPath || this . _rootPath ;
178+ if ( ! this . _rootPath ) {
179+ this . _logger . warn (
180+ 'no rootPath configured in extension or server, defaulting to cwd' ,
161181 ) ;
162182 }
183+ this . _loadConfigOptions . rootDir = this . _rootPath ;
184+
163185 this . _graphQLCache = await getGraphQLCache ( {
164186 parser : this . _parser ,
165187 loadConfigOptions : this . _loadConfigOptions ,
@@ -192,6 +214,21 @@ export class MessageProcessor {
192214 return null ;
193215 }
194216
217+ const settings = await this . _connection . workspace . getConfiguration ( {
218+ section : 'graphql-config' ,
219+ } ) ;
220+ if ( settings . rootDir && settings . rootDir !== this . _rootPath ) {
221+ this . _rootPath = settings . rootDir ;
222+ this . _loadConfigOptions . rootDir = settings . rootDir ;
223+
224+ this . _graphQLCache = await getGraphQLCache ( {
225+ parser : this . _parser ,
226+ loadConfigOptions : this . _loadConfigOptions ,
227+ config : this . _graphQLConfig ,
228+ } ) ;
229+ this . _languageService = new GraphQLLanguageService ( this . _graphQLCache ) ;
230+ }
231+
195232 if ( ! params || ! params . textDocument ) {
196233 throw new Error ( '`textDocument` argument is required.' ) ;
197234 }
@@ -579,9 +616,9 @@ export class MessageProcessor {
579616 return [ ] ;
580617 }
581618
582- const { query, range } = found ;
583- if ( range ) {
584- position . line -= range . start . line ;
619+ const { query, range : parentRange } = found ;
620+ if ( parentRange ) {
621+ position . line -= parentRange . start . line ;
585622 }
586623
587624 const result = await this . _languageService . getDefinition (
@@ -590,9 +627,42 @@ export class MessageProcessor {
590627 textDocument . uri ,
591628 ) ;
592629
630+ const inlineFragments : string [ ] = [ ] ;
631+
632+ visit (
633+ parse ( query , {
634+ allowLegacySDLEmptyFields : true ,
635+ allowLegacySDLImplementsInterfaces : true ,
636+ } ) ,
637+ {
638+ FragmentDefinition : ( node : FragmentDefinitionNode ) => {
639+ inlineFragments . push ( node . name . value ) ;
640+ } ,
641+ } ,
642+ ) ;
643+
593644 const formatted = result
594645 ? result . definitions . map ( res => {
595646 const defRange = res . range as Range ;
647+
648+ if ( parentRange && res . name ) {
649+ const isInline = inlineFragments . includes ( res . name ) ;
650+ const isEmbedded = DEFAULT_SUPPORTED_EXTENSIONS . includes (
651+ path . extname ( textDocument . uri ) ,
652+ ) ;
653+ if ( isInline && isEmbedded ) {
654+ const vOffset = parentRange . start . line ;
655+ defRange . setStart (
656+ ( defRange . start . line += vOffset ) ,
657+ defRange . start . character ,
658+ ) ;
659+ defRange . setEnd (
660+ ( defRange . end . line += vOffset ) ,
661+ defRange . end . character ,
662+ ) ;
663+ }
664+ }
665+
596666 return {
597667 // TODO: fix this hack!
598668 // URI is being misused all over this library - there's a link that
@@ -605,7 +675,7 @@ export class MessageProcessor {
605675 ? res . path
606676 : `file://${ path . resolve ( res . path ) } ` ,
607677 range : defRange ,
608- } ;
678+ } as Location ;
609679 } )
610680 : [ ] ;
611681
@@ -693,6 +763,7 @@ export class MessageProcessor {
693763
694764 return [ ] ;
695765 }
766+
696767 _getTextDocuments ( ) {
697768 return Array . from ( this . _textDocumentCache ) ;
698769 }
@@ -734,8 +805,8 @@ export class MessageProcessor {
734805 appendPath ?: string ,
735806 ) {
736807 const baseDir = this . _graphQLCache . getGraphQLConfig ( ) . dirpath ;
737- const baseName = path . basename ( baseDir ) ;
738- const basePath = path . join ( this . _tmpDirBase , baseName ) ;
808+ const workspaceName = path . basename ( baseDir ) ;
809+ const basePath = path . join ( this . _tmpDirBase , workspaceName ) ;
739810 let projectTmpPath = path . join ( basePath , 'projects' , project . name ) ;
740811 if ( ! existsSync ( projectTmpPath ) ) {
741812 mkdirp ( projectTmpPath ) ;
@@ -744,9 +815,10 @@ export class MessageProcessor {
744815 projectTmpPath = path . join ( projectTmpPath , appendPath ) ;
745816 }
746817 if ( prependWithProtocol ) {
747- projectTmpPath = `file://${ projectTmpPath } ` ;
818+ return `file://${ path . resolve ( projectTmpPath ) } ` ;
819+ } else {
820+ return path . resolve ( projectTmpPath ) ;
748821 }
749- return projectTmpPath ;
750822 }
751823 async _cacheSchemaFilesForProject ( project : GraphQLProjectConfig ) {
752824 const schema = project ?. schema ;
@@ -789,23 +861,27 @@ export class MessageProcessor {
789861 try {
790862 const schema = await this . _graphQLCache . getSchema ( project . name ) ;
791863 if ( schema ) {
792- const schemaText = printSchema ( schema , {
864+ let schemaText = printSchema ( schema , {
793865 commentDescriptions : true ,
794866 } ) ;
795867 // file:// protocol path
796- const uri = this . _getTmpProjectPath ( project , true , 'schema.graphql' ) ;
868+ const uri = this . _getTmpProjectPath (
869+ project ,
870+ true ,
871+ 'generated-schema.graphql' ,
872+ ) ;
797873
798874 // no file:// protocol for fs.writeFileSync()
799875 const fsPath = this . _getTmpProjectPath (
800876 project ,
801877 false ,
802- 'schema.graphql' ,
878+ 'generated- schema.graphql' ,
803879 ) ;
880+ schemaText = `# This is an automatically generated representation of your schema.\n# Any changes to this file will be overwritten and will not be\n# reflected in the resulting GraphQL schema\n\n${ schemaText } ` ;
804881
805882 const cachedSchemaDoc = this . _getCachedDocument ( uri ) ;
806883
807884 if ( ! cachedSchemaDoc ) {
808- console . log ( { fsPath } ) ;
809885 await writeFileAsync ( fsPath , schemaText , {
810886 encoding : 'utf-8' ,
811887 } ) ;
0 commit comments