Skip to content

Commit

Permalink
[language-services] Improve autocomplete suggestions when editing typ…
Browse files Browse the repository at this point in the history
…e system definitions (#2654)
  • Loading branch information
cshaver committed Aug 18, 2022
1 parent a792b35 commit d6ff4d7
Show file tree
Hide file tree
Showing 20 changed files with 582 additions and 60 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-timers-heal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'graphql-language-service': minor
---

Provide autocomplete suggestions for documents with type definitions
5 changes: 5 additions & 0 deletions .changeset/smart-cats-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'example-monaco-graphql-webpack': minor
---

Add schema SDL editor populated with the test schema
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ module.exports = {
'no-catch-shadow': 1,
'no-label-var': 1,
'no-restricted-globals': 0,
'no-shadow': 1,
'no-shadow': 'off',
'@typescript-eslint/no-shadow': 'error',
'no-undef-init': 0,
'no-undefined': 0,

Expand Down
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
],
"sourceMaps": true,
"preLaunchTask": "watch-vscode"
},
{
"type": "node",
"name": "jest watch",
"request": "launch",
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
"args": [
"--config",
"jest.config.js",
"--color",
"--runInBand",
"--watch",
"${relativeFile}"
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
5 changes: 4 additions & 1 deletion examples/monaco-graphql-webpack/babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ module.exports = {
require.resolve('@babel/preset-typescript'),
require.resolve('@babel/preset-react'),
],
plugins: [require.resolve('@babel/plugin-proposal-class-properties')],
plugins: [
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
],
};
26 changes: 24 additions & 2 deletions examples/monaco-graphql-webpack/src/editors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ query Example(

const variablesString =
localStorage.getItem('variables') ??
`{
"reviewEvent": "graphql",
`{
"reviewEvent": "graphql",
"name": true
}`;

const resultsString = `{}`;

const schemaSdlString = localStorage.getItem('schema-sdl') ?? ``;

const THEME = 'vs-dark';

export function createEditors() {
Expand Down Expand Up @@ -91,6 +93,24 @@ export function createEditors() {
},
);

const schemaModel = monaco.editor.createModel(
schemaSdlString,
GRAPHQL_LANGUAGE_ID,
monaco.Uri.file('/1/schema.graphqls'),
);

const schemaEditor = monaco.editor.create(
document.getElementById('schema-sdl') as HTMLElement,
{
model: schemaModel,
formatOnPaste: true,
formatOnType: true,
folding: true,
theme: THEME,
language: GRAPHQL_LANGUAGE_ID,
},
);

const resultsModel = monaco.editor.createModel(
resultsString,
'json',
Expand All @@ -113,7 +133,9 @@ export function createEditors() {
operationEditor,
variablesEditor,
resultsEditor,
schemaEditor,
operationModel,
variablesModel,
schemaModel,
};
}
1 change: 1 addition & 0 deletions examples/monaco-graphql-webpack/src/index.html.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
aria-atomic="true"
id="results"
></div>
<div id="schema-sdl"></div>
</div>
</div>
</div>
Expand Down
32 changes: 29 additions & 3 deletions examples/monaco-graphql-webpack/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ async function render() {
operationModel,
operationEditor,
variablesEditor,
schemaEditor,
resultsEditor,
variablesModel,
schemaModel,
} = editors;
const { schemaReloadButton, executeOpButton, schemaPicker } =
renderToolbar(toolbar);
Expand All @@ -59,9 +61,12 @@ async function render() {

const schema = await schemaFetcher.loadSchema();
if (schema) {
console.log('loaded schema', schema);
monacoGraphQLAPI.setSchemaConfig([
{ ...schema, fileMatch: [operationUri] },
{ ...schema, fileMatch: [operationUri, schemaModel.uri.toString()] },
]);

schemaEditor.setValue(schema.documentString || '');
}

monacoGraphQLAPI.setDiagnosticSettings({
Expand All @@ -86,6 +91,23 @@ async function render() {
localStorage.setItem('variables', variablesModel.getValue());
}, 200);
});
schemaModel.onDidChangeContent(() => {
setTimeout(async () => {
const value = schemaModel.getValue();
localStorage.setItem('schema-sdl', value);

const nextSchema = await schemaFetcher.overrideSchema(value);

if (nextSchema) {
monacoGraphQLAPI?.setSchemaConfig([
{
...nextSchema,
fileMatch: [operationUri, schemaModel.uri.toString()],
},
]);
}
}, 200);
});

/**
* Choosing a new schema
Expand All @@ -104,6 +126,7 @@ async function render() {
fileMatch: [operationModel.uri.toString()],
},
]);
schemaEditor.setValue(schemaResult.documentString || '');
}
}
},
Expand All @@ -112,8 +135,11 @@ async function render() {
/**
* Reloading your schema
*/
schemaReloadButton.addEventListener('click', () => {
schemaFetcher.loadSchema().then();
schemaReloadButton.addEventListener('click', async () => {
const schemaResult = await schemaFetcher.loadSchema();
if (schemaResult) {
schemaEditor.setValue(schemaResult.documentString || '');
}
});

/**
Expand Down
48 changes: 45 additions & 3 deletions examples/monaco-graphql-webpack/src/schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { getIntrospectionQuery } from 'graphql';
import {
buildClientSchema,
getIntrospectionQuery,
printSchema,
parse,
buildASTSchema,
} from 'graphql';
import type { SchemaConfig } from 'monaco-graphql/src/typings';
import { Uri } from 'monaco-editor';

Expand Down Expand Up @@ -33,6 +39,8 @@ class MySchemaFetcher {
private _options: typeof schemaOptions;
private _currentSchema: typeof schemaOptions[0];
private _schemaCache = new Map<string, SchemaConfig>();
private _schemaOverride = new Map<string, string>();

constructor(options = schemaOptions) {
this._options = options;
this._currentSchema = schemaOptions[0];
Expand All @@ -49,7 +57,10 @@ class MySchemaFetcher {
async getSchema() {
const cacheItem = this._schemaCache.get(this._currentSchema.value);
if (cacheItem) {
return cacheItem;
return {
...cacheItem,
documentString: this.getOverride() || cacheItem.documentString,
};
}
return this.loadSchema();
}
Expand Down Expand Up @@ -84,11 +95,16 @@ class MySchemaFetcher {
2,
),
});
const introspectionJSON = (await result.json()).data;
const documentString = printSchema(buildClientSchema(introspectionJSON));
this._schemaCache.set(url, {
introspectionJSON: (await result.json()).data,
introspectionJSON,
documentString,
uri: Uri.parse(url).toString(),
});

this.clearOverride();

setSchemaStatus('Schema Loaded');
} catch {
setSchemaStatus('Schema error');
Expand All @@ -98,8 +114,34 @@ class MySchemaFetcher {
}
async changeSchema(uri: string) {
this._currentSchema = this._options.find(opt => opt.value === uri)!;
this.clearOverride();
return this.getSchema();
}

getOverride() {
return this._schemaOverride.get(this._currentSchema.value);
}

clearOverride() {
this._schemaOverride.delete(this._currentSchema.value);
}

async overrideSchema(sdl: string) {
if (isValid(sdl)) {
this._schemaOverride.set(this._currentSchema.value, sdl);
return this.getSchema();
}
}
}

function isValid(sdl: string) {
try {
const ast = parse(sdl);
buildASTSchema(ast);
return true;
} catch {
return false;
}
}

export const schemaFetcher = new MySchemaFetcher(schemaOptions);
6 changes: 5 additions & 1 deletion examples/monaco-graphql-webpack/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ body {
}
#results {
align-items: stretch;
height: 90vh;
height: 45vh;
}
#schema-sdl {
align-items: stretch;
height: 45vh;
}

/* Toolbar */
Expand Down
28 changes: 0 additions & 28 deletions packages/codemirror-graphql/src/__tests__/hint-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ import {
GraphQLList,
GraphQLNonNull,
GraphQLString,
__Directive,
__EnumValue,
__Field,
__InputValue,
__Schema,
__Type,
} from 'graphql';
Expand Down Expand Up @@ -615,30 +611,6 @@ describe('graphql-hint', () => {
text: 'SubscriptionType',
description: 'This is a simple subscription type',
},
{
text: '__Schema',
description: __Schema.description,
},
{
text: '__Type',
description: __Type.description,
},
{
text: '__Field',
description: __Field.description,
},
{
text: '__InputValue',
description: __InputValue.description,
},
{
text: '__EnumValue',
description: __EnumValue.description,
},
{
text: '__Directive',
description: __Directive.description,
},
];
const expectedSuggestions = getExpectedSuggestions(list);
expect(suggestions?.list).toEqual(expectedSuggestions);
Expand Down
4 changes: 2 additions & 2 deletions packages/graphiql-toolkit/src/create-fetcher/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ export const createMultipartFetcher = (
// the static provided headers
...fetcherOpts?.headers,
},
}).then(response =>
meros<Extract<ExecutionResultPayload, { hasNext: boolean }>>(response, {
}).then(r =>
meros<Extract<ExecutionResultPayload, { hasNext: boolean }>>(r, {
multiple: true,
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ export class GraphQLLanguageService {
position,
undefined,
fragmentInfo,
{ uri: filePath },
);
}
return [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,5 @@ type Query {
inputTypeTest(args: InputType = {key: "key"}): TestType
deprecatedField: TestType @deprecated(reason: "Use test instead.")
}

union TestUnion = Droid | TestType
Loading

0 comments on commit d6ff4d7

Please sign in to comment.