Skip to content

Commit

Permalink
Create a lint diagnostic from invalid schema (#3463)
Browse files Browse the repository at this point in the history
* Create a lint diagnostic from invalid schema
* Create two-doors-shave.md
* add config option to show error on invalid schema
  • Loading branch information
imolorhe committed Nov 20, 2023
1 parent 57c2d7f commit e45ba17
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .changeset/two-doors-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"cm6-graphql": patch
---

Create a lint diagnostic from invalid schema
1 change: 1 addition & 0 deletions packages/cm6-graphql/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GraphQLSchema } from 'graphql';
import { ContextToken, CompletionItem } from 'graphql-language-service';
import { Position } from './helpers';
export interface GqlExtensionsOptions {
showErrorOnInvalidSchema?: boolean;
onShowInDocs?: (field?: string, type?: string, parentType?: string) => void;
onFillAllFields?: (
view: EditorView,
Expand Down
99 changes: 61 additions & 38 deletions packages/cm6-graphql/src/lint.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,78 @@
import { Diagnostic, linter } from '@codemirror/lint';
import { getDiagnostics } from 'graphql-language-service';
import { Position, posToOffset } from './helpers';
import { getSchema, optionsStateField, schemaStateField } from './state';
import {
getOpts,
getSchema,
optionsStateField,
schemaStateField,
} from './state';
import { Extension } from '@codemirror/state';
import { validateSchema } from 'graphql';

const SEVERITY = ['error', 'warning', 'info'] as const;

export const lint: Extension = linter(
view => {
try {
const schema = getSchema(view.state);
if (!schema) {
const schema = getSchema(view.state);
const options = getOpts(view.state);
if (!schema) {
return [];
}
const validationErrors = validateSchema(schema);
if (validationErrors.length) {
if (!options?.showErrorOnInvalidSchema) {
return [];
}
const results = getDiagnostics(view.state.doc.toString(), schema);

return results
.map((item): Diagnostic | null => {
if (!item.severity || !item.source) {
return null;
}
const combinedError = validationErrors.map(error => {
return error.message;
});

const calculatedFrom = posToOffset(
view.state.doc,
new Position(item.range.start.line, item.range.start.character),
);
const from = Math.max(
0,
Math.min(calculatedFrom, view.state.doc.length),
);
const calculatedRo = posToOffset(
view.state.doc,
new Position(item.range.end.line, item.range.end.character - 1),
);
const to = Math.min(
Math.max(from + 1, calculatedRo),
view.state.doc.length,
);
return {
from,
to: from === to ? to + 1 : to,
severity: SEVERITY[item.severity - 1],
// source: item.source, // TODO:
message: item.message,
actions: [], // TODO:
};
})
.filter((_): _ is Diagnostic => Boolean(_));
} catch {
return [];
return [
{
from: 0,
to: view.state.doc.length,
severity: 'error',
message: combinedError.join('\n'),
actions: [], // TODO:
},
];
}
const results = getDiagnostics(view.state.doc.toString(), schema);

return results
.map((item): Diagnostic | null => {
if (!item.severity || !item.source) {
return null;
}

const calculatedFrom = posToOffset(
view.state.doc,
new Position(item.range.start.line, item.range.start.character),
);
const from = Math.max(
0,
Math.min(calculatedFrom, view.state.doc.length),
);
const calculatedRo = posToOffset(
view.state.doc,
new Position(item.range.end.line, item.range.end.character - 1),
);
const to = Math.min(
Math.max(from + 1, calculatedRo),
view.state.doc.length,
);
return {
from,
to: from === to ? to + 1 : to,
severity: SEVERITY[item.severity - 1],
// source: item.source, // TODO:
message: item.message,
actions: [], // TODO:
};
})
.filter((_): _ is Diagnostic => Boolean(_));
},
{
needsRefresh(vu) {
Expand Down
9 changes: 8 additions & 1 deletion packages/cm6-graphql/src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,14 @@ export const getOpts = (state: EditorState) => {
return state.field(optionsStateField);
};

const defaultOpts: GqlExtensionsOptions = {
showErrorOnInvalidSchema: true,
};

export const stateExtensions = (
schema?: GraphQLSchema,
opts?: GqlExtensionsOptions,
) => [schemaStateField.init(() => schema), optionsStateField.init(() => opts)];
) => [
schemaStateField.init(() => schema),
optionsStateField.init(() => ({ ...defaultOpts, ...opts })),
];

0 comments on commit e45ba17

Please sign in to comment.