Skip to content

Commit df57cd2

Browse files
authored
Add hover syntax highlighting for types (#2065)
1 parent 989fca6 commit df57cd2

File tree

5 files changed

+41
-3
lines changed

5 files changed

+41
-3
lines changed

.changeset/real-boxes-clap.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'graphql-language-service': patch
3+
'graphql-language-service-interface': patch
4+
'graphql-language-service-server': patch
5+
---
6+
7+
Add an opt-in feature to generate markdown in hover elements, starting with highlighting type information. Enabled for the language server and also the language service and thus `monaco-graphql` as well.

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {
3535

3636
import { Kind, parse, print } from 'graphql';
3737
import { getAutocompleteSuggestions } from './getAutocompleteSuggestions';
38-
import { getHoverInformation } from './getHoverInformation';
38+
import { getHoverInformation, HoverConfig } from './getHoverInformation';
3939
import { validateQuery, getRange, DIAGNOSTIC_SEVERITY } from './getDiagnostics';
4040
import {
4141
getDefinitionQueryResultForFragmentSpread,
@@ -250,12 +250,13 @@ export class GraphQLLanguageService {
250250
query: string,
251251
position: IPosition,
252252
filePath: Uri,
253+
options?: HoverConfig,
253254
): Promise<Hover['contents']> {
254255
const projectConfig = this.getConfigForURI(filePath);
255256
const schema = await this._graphQLCache.getSchema(projectConfig.name);
256257

257258
if (schema) {
258-
return getHoverInformation(schema, query, position);
259+
return getHoverInformation(schema, query, position, undefined, options);
259260
}
260261
return '';
261262
}

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

+26-1
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@ import { AllTypeInfo, IPosition } from 'graphql-language-service-types';
2626
import { Hover } from 'vscode-languageserver-types';
2727
import { getTokenAtPosition, getTypeInfo } from './getAutocompleteSuggestions';
2828

29+
export type HoverConfig = { useMarkdown?: boolean };
30+
2931
export function getHoverInformation(
3032
schema: GraphQLSchema,
3133
queryText: string,
3234
cursor: IPosition,
3335
contextToken?: ContextToken,
36+
config?: HoverConfig,
3437
): Hover['contents'] {
3538
const token = contextToken || getTokenAtPosition(queryText, cursor);
3639

@@ -42,7 +45,7 @@ export function getHoverInformation(
4245
const kind = state.kind;
4346
const step = state.step;
4447
const typeInfo = getTypeInfo(schema, token.state);
45-
const options = { schema };
48+
const options = { ...config, schema };
4649

4750
// Given a Schema and a Token, produce the contents of an info tooltip.
4851
// To do this, create a div element that we will render "into" and then pass
@@ -52,17 +55,23 @@ export function getHoverInformation(
5255
(kind === 'AliasedField' && step === 2 && typeInfo.fieldDef)
5356
) {
5457
const into: string[] = [];
58+
renderMdCodeStart(into, options);
5559
renderField(into, typeInfo, options);
60+
renderMdCodeEnd(into, options);
5661
renderDescription(into, options, typeInfo.fieldDef);
5762
return into.join('').trim();
5863
} else if (kind === 'Directive' && step === 1 && typeInfo.directiveDef) {
5964
const into: string[] = [];
65+
renderMdCodeStart(into, options);
6066
renderDirective(into, typeInfo, options);
67+
renderMdCodeEnd(into, options);
6168
renderDescription(into, options, typeInfo.directiveDef);
6269
return into.join('').trim();
6370
} else if (kind === 'Argument' && step === 0 && typeInfo.argDef) {
6471
const into: string[] = [];
72+
renderMdCodeStart(into, options);
6573
renderArg(into, typeInfo, options);
74+
renderMdCodeEnd(into, options);
6675
renderDescription(into, options, typeInfo.argDef);
6776
return into.join('').trim();
6877
} else if (
@@ -71,7 +80,9 @@ export function getHoverInformation(
7180
'description' in typeInfo.enumValue
7281
) {
7382
const into: string[] = [];
83+
renderMdCodeStart(into, options);
7484
renderEnumValue(into, typeInfo, options);
85+
renderMdCodeEnd(into, options);
7586
renderDescription(into, options, typeInfo.enumValue);
7687
return into.join('').trim();
7788
} else if (
@@ -80,13 +91,26 @@ export function getHoverInformation(
8091
'description' in typeInfo.type
8192
) {
8293
const into: string[] = [];
94+
renderMdCodeStart(into, options);
8395
renderType(into, typeInfo, options, typeInfo.type);
96+
renderMdCodeEnd(into, options);
8497
renderDescription(into, options, typeInfo.type);
8598
return into.join('').trim();
8699
}
87100
return '';
88101
}
89102

103+
function renderMdCodeStart(into: string[], options: any) {
104+
if (options.useMarkdown) {
105+
text(into, '```graphql\n');
106+
}
107+
}
108+
function renderMdCodeEnd(into: string[], options: any) {
109+
if (options.useMarkdown) {
110+
text(into, '\n```');
111+
}
112+
}
113+
90114
function renderField(into: string[], typeInfo: AllTypeInfo, options: any) {
91115
renderQualifiedField(into, typeInfo, options);
92116
renderTypeAnnotation(into, typeInfo, options, typeInfo.type as GraphQLType);
@@ -168,6 +192,7 @@ function renderType(
168192
if (!t) {
169193
return;
170194
}
195+
171196
if (t instanceof GraphQLNonNull) {
172197
renderType(into, typeInfo, options, t.ofType);
173198
text(into, '!');

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

+1
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ export class MessageProcessor {
561561
query,
562562
toPosition(position),
563563
textDocument.uri,
564+
{ useMarkdown: true },
564565
);
565566

566567
return {

packages/graphql-language-service/src/LanguageService.ts

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
SchemaResponse,
2626
defaultSchemaBuilder,
2727
} from './schemaLoader';
28+
import { HoverConfig } from 'graphql-language-service-interface/src/getHoverInformation';
2829

2930
export type GraphQLLanguageConfig = {
3031
parser?: typeof parse;
@@ -203,10 +204,13 @@ export class LanguageService {
203204
_uri: string,
204205
documentText: string,
205206
position: IPosition,
207+
options?: HoverConfig,
206208
) =>
207209
getHoverInformation(
208210
(await this.getSchema()) as GraphQLSchema,
209211
documentText,
210212
position,
213+
undefined,
214+
{ useMarkdown: true, ...options },
211215
);
212216
}

0 commit comments

Comments
 (0)