Skip to content

Commit c2e27d7

Browse files
committed
feat(language-service): offset outline results for embedded gql
1 parent c88ed43 commit c2e27d7

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

packages/graphql-language-service-server/src/GraphQLLanguageService.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*
88
*/
99

10+
import * as path from 'node:path';
1011
import {
1112
DocumentNode,
1213
FragmentSpreadNode,
@@ -22,6 +23,7 @@ import {
2223
isTypeDefinitionNode,
2324
ArgumentNode,
2425
typeFromAST,
26+
Source as GraphQLSource,
2527
} from 'graphql';
2628

2729
import {
@@ -47,6 +49,7 @@ import {
4749
getTypeInfo,
4850
DefinitionQueryResponse,
4951
getDefinitionQueryResultForArgument,
52+
IRange,
5053
} from 'graphql-language-service';
5154

5255
import type { GraphQLCache } from './GraphQLCache';
@@ -359,8 +362,13 @@ export class GraphQLLanguageService {
359362
public async getDocumentSymbols(
360363
document: string,
361364
filePath: Uri,
365+
fileDocumentRange?: IRange | null,
362366
): Promise<SymbolInformation[]> {
363-
const outline = await this.getOutline(document);
367+
const outline = await this.getOutline(
368+
document,
369+
path.basename(filePath),
370+
fileDocumentRange?.start,
371+
);
364372
if (!outline) {
365373
return [];
366374
}
@@ -537,7 +545,20 @@ export class GraphQLLanguageService {
537545
);
538546
}
539547

540-
async getOutline(documentText: string): Promise<Outline | null> {
541-
return getOutline(documentText);
548+
async getOutline(
549+
documentText: string,
550+
documentName: string,
551+
documentOffset?: IPosition,
552+
): Promise<Outline | null> {
553+
return getOutline(
554+
new GraphQLSource(
555+
documentText,
556+
documentName,
557+
documentOffset && {
558+
column: documentOffset.character + 1,
559+
line: documentOffset.line + 1,
560+
},
561+
),
562+
);
542563
}
543564
}

packages/graphql-language-service/src/interface/getOutline.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
TokenKind,
1414
IPosition,
1515
OutlineTree,
16+
IRange,
1617
} from '../types';
1718

1819
import {
@@ -38,6 +39,7 @@ import {
3839
FieldDefinitionNode,
3940
EnumValueDefinitionNode,
4041
InputObjectTypeDefinitionNode,
42+
Source as GraphQLSource,
4143
} from 'graphql';
4244
import type { ASTReducer } from 'graphql/language/visitor';
4345

@@ -105,16 +107,16 @@ type OutlineTreeConverterType = {
105107
) => OutlineTreeResult;
106108
};
107109

108-
export function getOutline(documentText: string): Outline | null {
110+
export function getOutline(document: string | GraphQLSource): Outline | null {
109111
let ast;
110112
try {
111-
ast = parse(documentText);
113+
ast = parse(document);
112114
} catch {
113115
return null;
114116
}
115117

116118
type VisitorFns = Record<Kind, (node: ASTNode) => OutlineTreeResult>;
117-
const visitorFns = outlineTreeConverter(documentText) as VisitorFns;
119+
const visitorFns = outlineTreeConverter(document) as VisitorFns;
118120
const outlineTrees = visit(ast, {
119121
leave(node: ASTNode) {
120122
if (node.kind in visitorFns) {
@@ -127,13 +129,19 @@ export function getOutline(documentText: string): Outline | null {
127129
return { outlineTrees };
128130
}
129131

130-
function outlineTreeConverter(docText: string): OutlineTreeConverterType {
132+
function outlineTreeConverter(
133+
document: string | GraphQLSource,
134+
): OutlineTreeConverterType {
135+
const docText = typeof document === 'string' ? document : document.body;
136+
const { locationOffset }: Partial<GraphQLSource> =
137+
typeof document === 'string' ? {} : document;
131138
type MetaNode = Exclude<
132139
OutlineableNode,
133140
DocumentNode | SelectionSetNode | NameNode | InlineFragmentNode
134141
>;
135142
const meta = (node: ExclusiveUnion<MetaNode>): OutlineTreeResultMeta => {
136143
const range = locToRange(docText, node.loc!);
144+
applyOffsetToRange(range, locationOffset);
137145
return {
138146
representativeName: node.name,
139147
startPosition: range.start,
@@ -250,3 +258,24 @@ function concatMap<V>(arr: Readonly<V[]>, fn: Function): Readonly<V[]> {
250258
}
251259
return res;
252260
}
261+
262+
function applyOffsetToRange(
263+
range: IRange,
264+
locationOffset?: GraphQLSource['locationOffset'],
265+
) {
266+
if (!locationOffset) {
267+
return;
268+
}
269+
applyOffsetToPosition(range.start, locationOffset);
270+
applyOffsetToPosition(range.end, locationOffset);
271+
}
272+
273+
function applyOffsetToPosition(
274+
position: IPosition,
275+
locationOffset: GraphQLSource['locationOffset'],
276+
) {
277+
if (position.line === 1) {
278+
position.character += locationOffset.column - 1;
279+
}
280+
position.line += locationOffset.line - 1;
281+
}

0 commit comments

Comments
 (0)