diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a1b613ac..57d0f054 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,6 +62,21 @@ Complete your CLA here: npm test ``` +6. (optional) Link to `graphql/graphql-js` locally + + from `graphql-js` repository: + ```sh + yarn + yarn build + cd dist + yarn link + ``` + + then from this project: + ```sh + yarn link graphql + ``` + ## Release on NPM *Only core contributors may release to NPM.* diff --git a/package.json b/package.json index 680a9e19..d50ae132 100644 --- a/package.json +++ b/package.json @@ -54,10 +54,10 @@ "flow-bin": "0.68.0", "graphql": "^14.0.2", "graphql-language-service-interface": "^1.0.0-0", - "graphql-language-service-parser": "^0.1.0-0", - "graphql-language-service-server": "^1.0.0-0", - "graphql-language-service-types": "^0.1.0-0", - "graphql-language-service-utils": "^1.0.0-0", + "graphql-language-service-parser": "^1.2.2", + "graphql-language-service-server": "^2.0.0", + "graphql-language-service-types": "^1.2.2", + "graphql-language-service-utils": "^2.0.0", "lerna": "^2.0.0", "mocha": "4.1.0", "prettier": "1.13" diff --git a/packages/interface/src/GraphQLLanguageService.js b/packages/interface/src/GraphQLLanguageService.js index d3118d07..91a69dc6 100644 --- a/packages/interface/src/GraphQLLanguageService.js +++ b/packages/interface/src/GraphQLLanguageService.js @@ -47,12 +47,14 @@ const { UNION_TYPE_DEFINITION, SCALAR_TYPE_DEFINITION, INPUT_OBJECT_TYPE_DEFINITION, + INPUT_UNION_TYPE_DEFINITION, SCALAR_TYPE_EXTENSION, OBJECT_TYPE_EXTENSION, INTERFACE_TYPE_EXTENSION, UNION_TYPE_EXTENSION, ENUM_TYPE_EXTENSION, INPUT_OBJECT_TYPE_EXTENSION, + INPUT_UNION_TYPE_EXTENSION, DIRECTIVE_DEFINITION, FRAGMENT_SPREAD, OPERATION_DEFINITION, @@ -89,12 +91,14 @@ export class GraphQLLanguageService { case UNION_TYPE_DEFINITION: case SCALAR_TYPE_DEFINITION: case INPUT_OBJECT_TYPE_DEFINITION: + case INPUT_UNION_TYPE_EXTENSION: case SCALAR_TYPE_EXTENSION: case OBJECT_TYPE_EXTENSION: case INTERFACE_TYPE_EXTENSION: case UNION_TYPE_EXTENSION: case ENUM_TYPE_EXTENSION: case INPUT_OBJECT_TYPE_EXTENSION: + case INPUT_UNION_TYPE_DEFINITION: case DIRECTIVE_DEFINITION: return true; } @@ -261,6 +265,7 @@ export class GraphQLLanguageService { definition => definition.kind === OBJECT_TYPE_DEFINITION || definition.kind === INPUT_OBJECT_TYPE_DEFINITION || + definition.kind === INPUT_UNION_TYPE_DEFINITION || definition.kind === ENUM_TYPE_DEFINITION, ); diff --git a/packages/interface/src/__tests__/__schema__/HoverTestSchema.graphql b/packages/interface/src/__tests__/__schema__/HoverTestSchema.graphql index 5150c736..38798797 100644 --- a/packages/interface/src/__tests__/__schema__/HoverTestSchema.graphql +++ b/packages/interface/src/__tests__/__schema__/HoverTestSchema.graphql @@ -12,6 +12,8 @@ enum Color { BLUE } +inputUnion InputUnionType = String | Float | Boolean + union UnionType = String | Float | Boolean interface TestInterface { @@ -27,11 +29,11 @@ type TestType implements TestInterface { } type Query { - """ This is field documentation for Query.thing """ thing: TestType listOfThing: [TestType!] parameterizedField(id: String!): TestType cluck: Chicken unionField: UnionType + inputUnionTest(input: InputUnionType): UnionType } diff --git a/packages/interface/src/__tests__/__schema__/StarWarsSchema.graphql b/packages/interface/src/__tests__/__schema__/StarWarsSchema.graphql index 67d9c1a8..468a2633 100644 --- a/packages/interface/src/__tests__/__schema__/StarWarsSchema.graphql +++ b/packages/interface/src/__tests__/__schema__/StarWarsSchema.graphql @@ -51,14 +51,22 @@ input InputType { value: Int = 42 } +input AltInputType { + key: String! + string: String! +} + type TestType { testField: String } +inputUnion ExampleInputUnion = AltInputType | InputType + type Query { hero(episode: Episode): Character human(id: String!): Human droid(id: String!): Droid inputTypeTest(args: InputType = {key: "key"}): TestType + inputUnionTest(args: ExampleInputUnion): TestType deprecatedField: TestType @deprecated(reason: "Use test instead.") } diff --git a/packages/interface/src/__tests__/getAutocompleteSuggestions-test.js b/packages/interface/src/__tests__/getAutocompleteSuggestions-test.js index b148da30..c4c52fea 100644 --- a/packages/interface/src/__tests__/getAutocompleteSuggestions-test.js +++ b/packages/interface/src/__tests__/getAutocompleteSuggestions-test.js @@ -80,6 +80,7 @@ describe('getAutocompleteSuggestions', () => { {label: 'hero', detail: 'Character'}, {label: 'human', detail: 'Human'}, {label: 'inputTypeTest', detail: 'TestType'}, + {label: 'inputUnionTest', detail: 'TestType'}, ]); // Test for query text with empty lines @@ -97,6 +98,7 @@ query name { {label: 'hero', detail: 'Character'}, {label: 'human', detail: 'Human'}, {label: 'inputTypeTest', detail: 'TestType'}, + {label: 'inputUnionTest', detail: 'TestType'}, ]); }); @@ -107,6 +109,7 @@ query name { {label: 'hero', detail: 'Character'}, {label: 'human', detail: 'Human'}, {label: 'inputTypeTest', detail: 'TestType'}, + {label: 'inputUnionTest', detail: 'TestType'}, ]); }); diff --git a/packages/interface/src/getAutocompleteSuggestions.js b/packages/interface/src/getAutocompleteSuggestions.js index 5efd0bd2..e4d10369 100644 --- a/packages/interface/src/getAutocompleteSuggestions.js +++ b/packages/interface/src/getAutocompleteSuggestions.js @@ -25,6 +25,7 @@ import { GraphQLBoolean, GraphQLEnumType, GraphQLInputObjectType, + GraphQLInputUnionType, GraphQLList, SchemaMetaFieldDef, TypeMetaFieldDef, @@ -121,6 +122,7 @@ export function getAutocompleteSuggestions( kind === 'EnumValue' || (kind === 'ListValue' && step === 1) || (kind === 'ObjectField' && step === 2) || + (kind === 'InputUnion' && step === 2) || (kind === 'Argument' && step === 2) ) { return getSuggestionsForInputValues(token, typeInfo); @@ -503,6 +505,8 @@ function canUseDirective( return locations.indexOf('ENUM_VALUE') !== -1; case 'InputDef': return locations.indexOf('INPUT_OBJECT') !== -1; + case 'InputUnionDef': + return locations.indexOf('INPUT_UNION') !== -1; case 'InputValueDef': const prevStateKind = state.prevState && state.prevState.kind; switch (prevStateKind) { @@ -628,6 +632,13 @@ export function getTypeInfo( ? objectType.getFields() : null; break; + case 'InputUnionValue': + const inputUnionType = getNamedType(inputType); + objectFieldDefs = + inputUnionType instanceof GraphQLInputUnionType + ? inputUnionType.getFields() + : null; + break; case 'ObjectField': const objectField = state.name && objectFieldDefs ? objectFieldDefs[state.name] : null; diff --git a/packages/parser/src/Rules.js b/packages/parser/src/Rules.js index cb33f089..cc777fde 100644 --- a/packages/parser/src/Rules.js +++ b/packages/parser/src/Rules.js @@ -81,6 +81,8 @@ export const ParseRules: {[name: string]: ParseRule} = { return 'EnumDef'; case 'input': return 'InputDef'; + case 'inputUnion': + return 'InputUnionDef'; case 'extend': return 'ExtendDef'; case 'directive': @@ -196,6 +198,7 @@ export const ParseRules: {[name: string]: ParseRule} = { Type(token: Token) { return token.value === '[' ? 'ListType' : 'NonNullType'; }, + InputUnionValue: [p('{'), list('ObjectField'), p('}')], // NonNullType has been merged into ListType to simplify. ListType: [p('['), 'Type', p(']'), opt(p('!'))], NonNullType: ['NamedType', opt(p('!'))], @@ -252,6 +255,14 @@ export const ParseRules: {[name: string]: ParseRule} = { list('UnionMember', p('|')), ], UnionMember: ['NamedType'], + InputUnionDef: [ + word('inputUnion'), + name('atom'), + list('Directive'), + p('='), + list('InputUnionMember', p('|')), + ], + InputUnionMember: ['NamedType'], EnumDef: [ word('enum'), name('atom'), diff --git a/packages/server/src/GraphQLCache.js b/packages/server/src/GraphQLCache.js index 80c7a4bf..e22fe776 100644 --- a/packages/server/src/GraphQLCache.js +++ b/packages/server/src/GraphQLCache.js @@ -43,12 +43,14 @@ const { UNION_TYPE_DEFINITION, SCALAR_TYPE_DEFINITION, INPUT_OBJECT_TYPE_DEFINITION, + INPUT_UNION_TYPE_DEFINITION, SCALAR_TYPE_EXTENSION, OBJECT_TYPE_EXTENSION, INTERFACE_TYPE_EXTENSION, UNION_TYPE_EXTENSION, ENUM_TYPE_EXTENSION, INPUT_OBJECT_TYPE_EXTENSION, + INPUT_UNION_TYPE_EXTENSION, DIRECTIVE_DEFINITION, } = Kind; @@ -228,6 +230,9 @@ export class GraphQLCache implements GraphQLCacheInterface { InputObjectTypeDefinition(node) { existingObjectTypes.set(node.name.value, true); }, + InputUnionTypeDefinition(node) { + existingObjectTypes.set(node.name.value, true); + }, EnumTypeDefinition(node) { existingObjectTypes.set(node.name.value, true); }, @@ -603,12 +608,14 @@ export class GraphQLCache implements GraphQLCacheInterface { case UNION_TYPE_DEFINITION: case SCALAR_TYPE_DEFINITION: case INPUT_OBJECT_TYPE_DEFINITION: + case INPUT_UNION_TYPE_DEFINITION: case SCALAR_TYPE_EXTENSION: case OBJECT_TYPE_EXTENSION: case INTERFACE_TYPE_EXTENSION: case UNION_TYPE_EXTENSION: case ENUM_TYPE_EXTENSION: case INPUT_OBJECT_TYPE_EXTENSION: + case INPUT_UNION_TYPE_EXTENSION: case DIRECTIVE_DEFINITION: typeExtensions.push(definition); break; @@ -820,6 +827,7 @@ export class GraphQLCache implements GraphQLCacheInterface { if ( definition.kind === OBJECT_TYPE_DEFINITION || definition.kind === INPUT_OBJECT_TYPE_DEFINITION || + definition.kind === INPUT_UNION_TYPE_DEFINITION || definition.kind === ENUM_TYPE_DEFINITION ) { objectTypeDefinitions.set(definition.name.value, { diff --git a/packages/server/src/__tests__/__schema__/StarWarsSchema.graphql b/packages/server/src/__tests__/__schema__/StarWarsSchema.graphql index 5f51cc74..cbb26e78 100644 --- a/packages/server/src/__tests__/__schema__/StarWarsSchema.graphql +++ b/packages/server/src/__tests__/__schema__/StarWarsSchema.graphql @@ -40,13 +40,21 @@ input InputType { value: Int = 42 } +input AltInputType { + key: String! + value: String +} + type TestType { testField: String } +inputUnion ExampleInputUnion = InputType | AltInputType + type Query { hero(episode: Episode): Character human(id: String!): Human droid(id: String!): Droid inputTypeTest(args: InputType = {key: "key"}): TestType + inputUnionTest(args: ExampleInputUnion): TestType } diff --git a/yarn.lock b/yarn.lock index e5aea5b4..7ca2decd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1696,7 +1696,7 @@ graphql-import@^0.4.4: dependencies: lodash "^4.17.4" -graphql-language-service-interface@^1.0.0-0, graphql-language-service-interface@^1.3.2: +graphql-language-service-interface@^1.0.0-0: version "1.3.2" resolved "https://registry.yarnpkg.com/graphql-language-service-interface/-/graphql-language-service-interface-1.3.2.tgz#4bd5d49e23766c3d2ab65d110f26f10e321cc000" dependencies: @@ -1705,32 +1705,7 @@ graphql-language-service-interface@^1.0.0-0, graphql-language-service-interface@ graphql-language-service-types "^1.2.2" graphql-language-service-utils "^1.2.2" -graphql-language-service-parser@^0.1.0-0: - version "0.1.14" - resolved "https://registry.yarnpkg.com/graphql-language-service-parser/-/graphql-language-service-parser-0.1.14.tgz#dd25abda5dcff4f2268c9a19e026004271491661" - dependencies: - graphql-language-service-types "^0.1.14" - -graphql-language-service-server@^1.0.0-0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/graphql-language-service-server/-/graphql-language-service-server-1.3.2.tgz#9423ede58a5b7bcaa3bbcb42f39a6c9626f6787d" - dependencies: - babylon "^6.17.4" - fb-watchman "^2.0.0" - glob "^7.1.2" - graphql-config "2.0.1" - graphql-language-service-interface "^1.3.2" - graphql-language-service-types "^1.2.2" - graphql-language-service-utils "^1.2.2" - nullthrows "^1.0.0" - vscode-jsonrpc "^3.3.0" - vscode-languageserver "^3.3.0" - -graphql-language-service-types@^0.1.0-0, graphql-language-service-types@^0.1.14: - version "0.1.14" - resolved "https://registry.yarnpkg.com/graphql-language-service-types/-/graphql-language-service-types-0.1.14.tgz#e6112785fc23ea8222f59a7f00e61b359f263c88" - -graphql-language-service-utils@^1.0.0-0, graphql-language-service-utils@^1.2.2: +graphql-language-service-utils@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/graphql-language-service-utils/-/graphql-language-service-utils-1.2.2.tgz#d31d4b4288085bd31d1bb8efc35790d69e496cae" dependencies: