Skip to content

Commit

Permalink
feat: convert LSP from flow to typescript (#957) @acao @Neitch @benjie
Browse files Browse the repository at this point in the history
* convert `graphql-language-types`, `graphql-language-service-utils`, `graphql-language-service-parser` and `graphql-language-service-interface` from flow to typescript
* introduce `RuleKind` `enum`
* make jest work with typescript
* make eslint work with typescript
* re-add flowtypes for TS packages
  • Loading branch information
acao committed Oct 4, 2019
1 parent f6b0e50 commit 36ed669
Show file tree
Hide file tree
Showing 87 changed files with 3,564 additions and 2,434 deletions.
33 changes: 29 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@

module.exports = {
root: true,

parser: 'babel-eslint',

parserOptions: {
ecmaVersion: 7,
sourceType: 'module',
Expand All @@ -22,7 +20,6 @@ module.exports = {
experimentalObjectRestSpread: true,
},
},

// https://github.com/sindresorhus/globals/blob/master/globals.json
env: {
atomtest: true,
Expand All @@ -33,7 +30,7 @@ module.exports = {
browser: true,
},

extends: ['prettier'],
extends: ['prettier', 'plugin:import/typescript'],

globals: {
atom: false,
Expand Down Expand Up @@ -292,6 +289,34 @@ module.exports = {
plugins: ['babel', 'import', 'flowtype', 'prefer-object-spread'],

overrides: [
// Rules for TypeScript only
{
files: ['*.ts', '*.tsx'],
parser: '@typescript-eslint/parser',
rules: {
'no-unused-vars': 'off',
},
},
// Rules for Flow only
{
files: ['*.js', '*.jsx'],
rules: {
// flowtype (https://github.com/gajus/eslint-plugin-flowtype)
'flowtype/boolean-style': 1,
'flowtype/define-flow-type': 1,
'flowtype/no-dupe-keys': 0,
'flowtype/no-primitive-constructor-types': 1,
'flowtype/no-weak-types': 0,
'flowtype/require-parameter-type': 0,
'flowtype/require-return-type': 0,
'flowtype/require-valid-file-annotation': 0,
'flowtype/require-variable-type': 0,
'flowtype/sort-keys': 0,
'flowtype/type-id-match': 0,
'flowtype/use-flow-type': 1,
'flowtype/valid-syntax': 0,
},
},
{
// Converted from 'dependencies' options in ancient config
files: ['**/spec/**', '**/sample-*/**'],
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ dist
node_modules/
npm-debug.log
lerna-debug.log
**/tsconfig.tsbuildinfo
19 changes: 12 additions & 7 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
const path = require('path');
const { jsWithTs: tsjPreset } = require('ts-jest/presets');
const { jsWithBabel: jsWithBabelPreset } = require('ts-jest/presets');

module.exports = {
globals: {
'ts-jest': {
tsConfig: './tsconfig.base.json'
}
},
verbose: true,
clearMocks: true,
collectCoverage: true,
setupFiles: [path.join(__dirname, '/resources/enzyme.config.js')],
testMatch: [
'<rootDir>/packages/*/src/**/*-test.js',
'<rootDir>/packages/*/src/**/*.spec.js',
'<rootDir>/packages/*/src/**/*-test.{js,ts}',
'<rootDir>/packages/*/src/**/*.spec.{js,ts}',
],
transform: {
'^.+\\.jsx?$': require.resolve('./resources/jestBabelTransform'),
...tsjPreset.transform,
...jsWithBabelPreset.transform
},
testEnvironment: require.resolve('jest-environment-jsdom-global'),
testPathIgnorePatterns: [
'node_modules',
'dist',
'codemirror-graphql',
],
testPathIgnorePatterns: ['node_modules', 'dist', 'codemirror-graphql'],
collectCoverageFrom: [
'**/src/**/*.{js,jsx}',
'!**/node_modules/**',
Expand Down
17 changes: 11 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
}
},
"scripts": {
"build": "lerna run build",
"build": "tsc --build && lerna run build --scope codemirror-graphql --scope graphiql --scope graphql-language-service --scope graphql-language-service-server",
"test": "yarn run lint && yarn run check && yarn run build && yarn run testonly",
"testonly": "jest && lerna run test --scope codemirror-graphql",
"t": "yarn run testonly",
"lint": "eslint --ext js,ts,jsx,tsx . || (printf '\\033[33mTry: \\033[7m yarn run lint -- --fix \\033[0m\\n' && exit 1)",
"lint-check": "eslint --print-config .eslintrc.js | eslint-config-prettier-check",
"lint": "eslint --ext=ts,js,jsx,tsx . || (printf '\\033[33mTry: \\033[7m yarn run lint -- --fix \\033[0m\\n' && exit 1)",
"lint:fix": "eslint --ext=ts,js,jsx,tsx . --fix",
"lint:check": "eslint --print-config .eslintrc.js | eslint-config-prettier-check",
"check": "flow check --show-all-errors",
"prepublish": "node resources/prepublish.js",
"pretty": "node resources/pretty.js",
Expand All @@ -47,7 +48,9 @@
"@commitlint/cli": "^8.1.0",
"@commitlint/config-conventional": "^8.1.0",
"@commitlint/config-lerna-scopes": "^8.1.0",
"babel-eslint": "^10.0.3",
"@types/jest": "^24.0.18",
"@typescript-eslint/parser": "^2.3.1",
"babel-eslint": "^10.0.1",
"chai": "4.2.0",
"codecov": "^3.5.0",
"conventional-changelog-conventionalcommits": "^4.1.0",
Expand All @@ -60,13 +63,15 @@
"eslint-plugin-react": "7.14.3",
"fetch-mock": "^6.0.0",
"flow-bin": "^0.101.0",
"graphql": "^14.3.1",
"graphql": "^14.5.2",
"husky": "^3.0.5",
"jest": "^24.8.0",
"jest-environment-jsdom": "^24.8.0",
"jest-environment-jsdom-global": "^1.2.0",
"lerna": "^3.16.4",
"mocha": "6.1.4",
"prettier": "^1.18.2"
"prettier": "^1.18.2",
"ts-jest": "^24.1.0",
"typescript": "^3.6.3"
}
}
18 changes: 9 additions & 9 deletions packages/codemirror-graphql/resources/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@ function checkFiles(filepaths) {
.then(testSuccess =>
lintFiles(filepaths).then(lintSuccess =>
typecheckStatus().then(
typecheckSuccess => testSuccess && lintSuccess && typecheckSuccess,
),
),
typecheckSuccess => testSuccess && lintSuccess && typecheckSuccess
)
)
)
.catch(() => false)
.then(success => {
process.stdout.write(
'\n' + (success ? '' : '\x07') + green(invert('watching...')),
'\n' + (success ? '' : '\x07') + green(invert('watching...'))
);
});
}
Expand All @@ -129,7 +129,7 @@ function parseFiles(filepaths) {
srcPath(filepath),
]);
}
}),
})
);
}

Expand All @@ -141,8 +141,8 @@ function runTests(filepaths) {
['--reporter', 'progress', '--require', 'resources/mocha-bootload'].concat(
allTests(filepaths)
? filepaths.map(srcPath)
: ['src/**/__tests__/**/*.js'],
),
: ['src/**/__tests__/**/*.js']
)
).catch(() => false);
}

Expand All @@ -158,14 +158,14 @@ function lintFiles(filepaths) {
.catch(() => false)
.then(success => {
console.log(
CLEARLINE + ' ' + (success ? CHECK : X) + ' ' + filepath,
CLEARLINE + ' ' + (success ? CHECK : X) + ' ' + filepath
);
return prevSuccess && success;
});
}
return prevSuccess;
}),
Promise.resolve(true),
Promise.resolve(true)
);
}

Expand Down
24 changes: 12 additions & 12 deletions packages/codemirror-graphql/src/__tests__/hint-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('graphql-hint', () => {
it('attaches a GraphQL hint function with correct mode/hint options', async () => {
const editor = await createEditorWithHint();
expect(editor.getHelpers(editor.getCursor(), 'hint')).to.not.have.lengthOf(
0,
0
);
});

Expand All @@ -72,11 +72,11 @@ describe('graphql-hint', () => {
const suggestions = await getHintSuggestions('{ ', { line: 0, ch: 2 });
const fieldConfig = TestSchema.getQueryType().getFields();
const fieldNames = Object.keys(fieldConfig).filter(
name => !fieldConfig[name].isDeprecated,
name => !fieldConfig[name].isDeprecated
);
checkSuggestions(
fieldNames.concat(['__typename', '__schema', '__type']),
suggestions.list,
suggestions.list
);

const fieldTypes = fieldNames.map(name => fieldConfig[name].type);
Expand All @@ -85,7 +85,7 @@ describe('graphql-hint', () => {
item =>
item.text !== '__schema' &&
item.text !== '__type' &&
item.text !== '__typename',
item.text !== '__typename'
)
.map(item => item.type);
expect(fieldTypes).to.deep.equal(expectedTypes);
Expand All @@ -99,7 +99,7 @@ describe('graphql-hint', () => {
const fieldConfig = TestSchema.getType('First').getFields();
checkSuggestions(
[...Object.keys(fieldConfig), '__typename'],
suggestions.list,
suggestions.list
);
});

Expand Down Expand Up @@ -161,7 +161,7 @@ describe('graphql-hint', () => {
it('provides correct directive suggestions on args definitions', async () => {
const suggestions = await getHintSuggestions(
'type Type { field(arg: String @',
{ line: 0, ch: 31 },
{ line: 0, ch: 31 }
);
const directiveNames = ['onArg', 'onAllDefs'];
checkSuggestions(directiveNames, suggestions.list);
Expand Down Expand Up @@ -209,23 +209,23 @@ describe('graphql-hint', () => {
ch: 21,
});
const testInputNames = Object.keys(
TestSchema.getType('TestInput').getFields(),
TestSchema.getType('TestInput').getFields()
);
checkSuggestions(testInputNames, suggestions.list);
});

it('provides fragment name suggestion', async () => {
const suggestions = await getHintSuggestions(
'fragment Foo on Test { id } query { ...',
{ line: 0, ch: 40 },
{ line: 0, ch: 40 }
);
checkSuggestions(['Foo'], suggestions.list);
});

it('provides fragment names for fragments defined lower', async () => {
const suggestions = await getHintSuggestions(
'query { ... } fragment Foo on Test { id }',
{ line: 0, ch: 11 },
{ line: 0, ch: 11 }
);
checkSuggestions(['Foo'], suggestions.list);
});
Expand All @@ -237,15 +237,15 @@ describe('graphql-hint', () => {
'fragment Baz on Second { name } ' +
'fragment Qux on TestUnion { name } ' +
'fragment Nrf on Test { id }',
{ line: 0, ch: 31 },
{ line: 0, ch: 31 }
);
checkSuggestions(['Bar', 'Baz', 'Qux'], suggestions.list);
});

it('provides correct field name suggestion inside inline fragment', async () => {
const suggestions = await getHintSuggestions(
'fragment Foo on TestUnion { ... on First { ',
{ line: 0, ch: 43 },
{ line: 0, ch: 43 }
);
const fieldNames = Object.keys(TestSchema.getType('First').getFields());
fieldNames.push('__typename');
Expand All @@ -255,7 +255,7 @@ describe('graphql-hint', () => {
it('provides correct field name suggestion inside typeless inline fragment', async () => {
const suggestions = await getHintSuggestions(
'fragment Foo on First { ... { ',
{ line: 0, ch: 30 },
{ line: 0, ch: 30 }
);
const fieldNames = Object.keys(TestSchema.getType('First').getFields());
fieldNames.push('__typename');
Expand Down
2 changes: 1 addition & 1 deletion packages/codemirror-graphql/src/__tests__/lint-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('graphql-lint', () => {
it('attaches a GraphQL lint function with correct mode/lint options', () => {
const editor = createEditorWithLint();
expect(editor.getHelpers(editor.getCursor(), 'lint')).to.not.have.lengthOf(
0,
0
);
});

Expand Down
14 changes: 7 additions & 7 deletions packages/codemirror-graphql/src/__tests__/mode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,25 @@ describe('graphql-mode', () => {

it('parses Relay-style anonymous FragmentDefinitions', () => {
CodeMirror.runMode('fragment on Test { id }', 'graphql', (token, style) =>
expect(style).to.not.equal('invalidchar'),
expect(style).to.not.equal('invalidchar')
);
});

it('parses inline fragments with optional syntax correctly', () => {
CodeMirror.runMode(
'{ ... on OptionalType { name } }',
'graphql',
(token, style) => expect(style).to.not.equal('invalidchar'),
(token, style) => expect(style).to.not.equal('invalidchar')
);

CodeMirror.runMode('{ ... { name } }', 'graphql', (token, style) =>
expect(style).to.not.equal('invalidchar'),
expect(style).to.not.equal('invalidchar')
);

CodeMirror.runMode(
'{ ... @optionalDirective { name } }',
'graphql',
(token, style) => expect(style).to.not.equal('invalidchar'),
(token, style) => expect(style).to.not.equal('invalidchar')
);
});

Expand Down Expand Up @@ -88,7 +88,7 @@ describe('graphql-mode', () => {
it('parses schema-kitchen-sink query without invalidchar', () => {
const schemaKitchenSink = readFileSync(
join(__dirname, '/schema-kitchen-sink.graphql'),
{ encoding: 'utf8' },
{ encoding: 'utf8' }
);

CodeMirror.runMode(schemaKitchenSink, 'graphql', (token, style) => {
Expand All @@ -110,7 +110,7 @@ describe('graphql-mode', () => {
'graphql',
(token, style) => {
expect(style).to.not.equal('invalidchar');
},
}
);

CodeMirror.runMode(
Expand All @@ -124,7 +124,7 @@ describe('graphql-mode', () => {
'graphql',
(token, style) => {
expect(style).to.not.equal('invalidchar');
},
}
);
});
});
2 changes: 1 addition & 1 deletion packages/codemirror-graphql/src/hint.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ CodeMirror.registerHelper('hint', 'graphql', (editor, options) => {
schema,
editor.getValue(),
cur,
token,
token
);
/**
* GraphQL language service responds to the autocompletion request with
Expand Down
4 changes: 2 additions & 2 deletions packages/codemirror-graphql/src/jump.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @flow
*
*
*/

import CodeMirror from 'codemirror';
Expand Down

0 comments on commit 36ed669

Please sign in to comment.