Skip to content

Commit

Permalink
[WIP] Integrate graphql-js experimental parser
Browse files Browse the repository at this point in the history
  • Loading branch information
thenamankumar committed Aug 30, 2020
1 parent 6114f2a commit 4ce47bb
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 15 deletions.
20 changes: 5 additions & 15 deletions packages/codemirror-graphql/src/mode.js
Expand Up @@ -8,12 +8,7 @@
*/

import CodeMirror from 'codemirror';
import {
LexRules,
ParseRules,
isIgnored,
onlineParser,
} from 'graphql-language-service-parser';
import { GraphqlParser } from 'graphql-language-service-parser';

/**
* The GraphQL mode is defined as a tokenizer along with a list of rules, each
Expand All @@ -36,16 +31,11 @@ import {
* which contains the relevant information to produce valuable typeaheads.
*/
CodeMirror.defineMode('graphql', config => {
const parser = onlineParser({
eatWhitespace: stream => stream.eatWhile(isIgnored),
lexRules: LexRules,
parseRules: ParseRules,
editorConfig: { tabSize: config.tabSize },
});
const parser = new GraphqlParser({ tabSize: config.tabSize });

return {
config,
startState: parser.startState,
startState: GraphqlParser.startState,
token: parser.token,
indent,
electricInput: /^\s*[})\]]/,
Expand All @@ -55,6 +45,7 @@ CodeMirror.defineMode('graphql', config => {
pairs: '()[]{}""',
explode: '()[]{}',
},
copyState: GraphqlParser.copyState,
};
});

Expand All @@ -65,7 +56,6 @@ function indent(state, textAfter) {
const level =
!levels || levels.length === 0
? state.indentLevel
: levels[levels.length - 1] -
(this.electricInput.test(textAfter) ? 1 : 0);
: levels[levels.length - 1] - (this.electricInput.test(textAfter) ? 1 : 0);
return level * this.config.indentUnit;
}
83 changes: 83 additions & 0 deletions packages/graphql-language-service-parser/src/GraphqlParser.ts
@@ -0,0 +1,83 @@
import { OnlineParser, OnlineParserState, TokenKind } from 'graphql/experimentalOnlineParser';
import CharacterStream from './CharacterStream';
import { isIgnored, LexRules } from './Rules';
const styles = require('./styles.json');

export interface State extends ParserState {
name: string | null;
type: string | null;
prevState: State | null;
}

export default class GraphqlParser {
config: any;

constructor(config = {}) {
this.config = config;
}

static startState = (): State => {
const state: any = OnlineParser.startState();
state.prevState = null;

return state;
};

static copyState = (state: State): State => {
const newState: any = OnlineParser.copyState(state);
newState.prevState = state.prevState;

return newState as State;
};

token(stream: CharacterStream, state: State): string {
const prevState = GraphqlParser.copyState(state);

if (stream.eatWhile(isIgnored)) {
return 'ws';
}

if (stream.eol()) {
return 'invalidchar';
}

const source = ((stream.match(/.*/, false) as Array<string>) || [])[0] || '';
const parserState = OnlineParser.copyState(state);
const parser = new OnlineParser(source, parserState, this.config);

const token = parser.parseToken();

if (token.kind !== 'Invalid' && token.value) {
Object.assign(state, parserState);
if (token.kind === TokenKind.PUNCTUATION) {
stream.match(LexRules.Punctuation);
} else {
stream.match(token.value);
}
} else {
stream.skipToEnd();
}

state.prevState = prevState;

return styles[token.tokenName] || styles[token.ruleName] || styles[token.kind] || '';
}
}

export type ContextToken = {
start: number;
end: number;
string: string;
state: State;
style: string;
};

export type ContextTokenForCodeMirror = {
start: number;
end: number;
string: string;
type: string | null;
state: State;
};

export type ContextTokenUnion = ContextToken | ContextTokenForCodeMirror;
2 changes: 2 additions & 0 deletions packages/graphql-language-service-parser/src/index.ts
Expand Up @@ -15,4 +15,6 @@ export { butNot, list, opt, p, t } from './RuleHelpers';

export { default as onlineParser } from './onlineParser';

export { default as GraphqlParser } from './GraphqlParser';

export * from './types';

0 comments on commit 4ce47bb

Please sign in to comment.