diff --git a/src/printer-graphql.js b/src/printer-graphql.js index b5fbd6f27..e9fdfb637 100644 --- a/src/printer-graphql.js +++ b/src/printer-graphql.js @@ -10,6 +10,8 @@ const group = docBuilders.group; const indent = docBuilders.indent; const ifBreak = docBuilders.ifBreak; +const util = require("./util"); + function genericPrint(path, options, print) { const n = path.getValue(); if (!n) { @@ -69,7 +71,16 @@ function genericPrint(path, options, print) { return concat([ "{", indent( - concat([hardline, join(hardline, path.map(print, "selections"))]) + concat([ + hardline, + join( + hardline, + path.call( + selectionsPath => printSequence(selectionsPath, options, print), + "selections" + ) + ) + ]) ), hardline, "}" @@ -89,7 +100,10 @@ function genericPrint(path, options, print) { softline, join( concat([ifBreak("", ", "), softline]), - path.map(print, "arguments") + path.call( + argsPath => printSequence(argsPath, options, print), + "arguments" + ) ) ]) ), @@ -184,7 +198,10 @@ function genericPrint(path, options, print) { softline, join( concat([ifBreak("", ", "), softline]), - path.map(print, "arguments") + path.call( + argsPath => printSequence(argsPath, options, print), + "arguments" + ) ) ]) ), @@ -224,7 +241,16 @@ function genericPrint(path, options, print) { " {", n.fields.length > 0 ? indent( - concat([hardline, join(hardline, path.map(print, "fields"))]) + concat([ + hardline, + join( + hardline, + path.call( + fieldsPath => printSequence(fieldsPath, options, print), + "fields" + ) + ) + ]) ) : "", hardline, @@ -244,7 +270,10 @@ function genericPrint(path, options, print) { softline, join( concat([ifBreak("", ", "), softline]), - path.map(print, "arguments") + path.call( + argsPath => printSequence(argsPath, options, print), + "arguments" + ) ) ]) ), @@ -273,7 +302,10 @@ function genericPrint(path, options, print) { softline, join( concat([ifBreak("", ", "), softline]), - path.map(print, "arguments") + path.call( + argsPath => printSequence(argsPath, options, print), + "arguments" + ) ) ]) ), @@ -294,7 +326,16 @@ function genericPrint(path, options, print) { " {", n.values.length > 0 ? indent( - concat([hardline, join(hardline, path.map(print, "values"))]) + concat([ + hardline, + join( + hardline, + path.call( + valuesPath => printSequence(valuesPath, options, print), + "values" + ) + ) + ]) ) : "", hardline, @@ -327,7 +368,16 @@ function genericPrint(path, options, print) { " {", n.fields.length > 0 ? indent( - concat([hardline, join(hardline, path.map(print, "fields"))]) + concat([ + hardline, + join( + hardline, + path.call( + fieldsPath => printSequence(fieldsPath, options, print), + "fields" + ) + ) + ]) ) : "", hardline, @@ -344,7 +394,13 @@ function genericPrint(path, options, print) { ? indent( concat([ hardline, - join(hardline, path.map(print, "operationTypes")) + join( + hardline, + path.call( + opsPath => printSequence(opsPath, options, print), + "operationTypes" + ) + ) ]) ) : "", @@ -369,7 +425,16 @@ function genericPrint(path, options, print) { " {", n.fields.length > 0 ? indent( - concat([hardline, join(hardline, path.map(print, "fields"))]) + concat([ + hardline, + join( + hardline, + path.call( + fieldsPath => printSequence(fieldsPath, options, print), + "fields" + ) + ) + ]) ) : "", hardline, @@ -457,4 +522,21 @@ function printDirectives(path, print, n) { ]); } +function printSequence(sequencePath, options, print) { + const count = sequencePath.getValue().length; + + return sequencePath.map((path, i) => { + const printed = print(path); + + if ( + util.isNextLineEmpty(options.originalText, path.getValue()) && + i < count - 1 + ) { + return concat([printed, hardline]); + } + + return printed; + }); +} + module.exports = genericPrint; diff --git a/tests/graphql_directives/__snapshots__/jsfmt.spec.js.snap b/tests/graphql_directives/__snapshots__/jsfmt.spec.js.snap index 925e104aa..b116650a5 100644 --- a/tests/graphql_directives/__snapshots__/jsfmt.spec.js.snap +++ b/tests/graphql_directives/__snapshots__/jsfmt.spec.js.snap @@ -37,6 +37,7 @@ fragment YouCanHaveDirectivesHereToo on SomeType @yesReally(what: "yes") { ... @notEvenATypeHere(args: [1, 2, 3]) { hello } + thisFieldHasALotOfDirectives @thisIsthefirst @thisIsTheSecond diff --git a/tests/graphql_newline/__snapshots__/jsfmt.spec.js.snap b/tests/graphql_newline/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..7efb263d3 --- /dev/null +++ b/tests/graphql_newline/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,274 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`directive_decl.graphql 1`] = ` +directive @dir( + # comment + arg1: String + + + # comment + arg2: String + arg3: String + +) on Field +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +directive @dir( + # comment + arg1: String + + # comment + arg2: String + arg3: String +) on Field + +`; + +exports[`directives.graphql 1`] = ` +query MyQuery @directive( + arg: 5 + + # comment + arg2: 10 + +) { + field @skip( + if: true + + # comment + cursor: 10 + + ) @nope + otherField + ...fragmentSpread, @include(if: ["this isn't even a boolean", "wow, that's really odd",,,,,]) +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +query MyQuery + @directive( + arg: 5 + + # comment + arg2: 10 + ) { + field + @skip( + if: true + + # comment + cursor: 10 + ) + @nope + otherField + ...fragmentSpread + @include(if: ["this isn't even a boolean", "wow, that's really odd"]) +} + +`; + +exports[`enum.graphql 1`] = ` +enum State { + # pending state + PENDING + + # visible states + VISIBLE + INVISIBLE + + # archive state + ARCHIVED +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +enum State { + # pending state + PENDING + + # visible states + VISIBLE + INVISIBLE + + # archive state + ARCHIVED +} + +`; + +exports[`fields.graphql 1`] = ` +query MyFirstQuery { + # comment + field { + + subfield + + # comment + subfield + + } + + field + #comment + field + +} + +mutation MyFirstMutation { + + # comment + name + + comment # comment + kind + +} + +subscription MySubscription { + + name + + comment + kind + +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +query MyFirstQuery { + # comment + field { + subfield + + # comment + subfield + } + + field + #comment + field +} + +mutation MyFirstMutation { + # comment + name + + comment # comment + kind +} + +subscription MySubscription { + name + + comment + kind +} + +`; + +exports[`input.graphql 1`] = ` +input Params { + # Id + id: ID + + # Name + name: String + +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +input Params { + # Id + id: ID + + # Name + name: String +} + +`; + +exports[`interface.graphql 1`] = ` +interface Actor { + # Id + id: ID + + # Actor fields + name: String + kind: String + +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +interface Actor { + # Id + id: ID + + # Actor fields + name: String + kind: String +} + +`; + +exports[`object_type_def.graphql 1`] = ` +type Artist implements Node, Entity { + # The ID of an object + id: ID! + + # The MBID of the entity. + mbid: MBID! + + # A list of recordings linked to this entity. + recordings(after: String, first: Int): RecordingConnection + + # A list of releases linked to this entity. + releases( + # Filter by one or more release group types. + type: [ReleaseGroupType] + + # Filter by one or more release statuses. + status: [ReleaseStatus] + after: String + first: Int + ): ReleaseConnection + +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +type Artist implements Node, Entity { + # The ID of an object + id: ID! + + # The MBID of the entity. + mbid: MBID! + + # A list of recordings linked to this entity. + recordings(after: String, first: Int): RecordingConnection + + # A list of releases linked to this entity. + releases( + # Filter by one or more release group types. + type: [ReleaseGroupType] + + # Filter by one or more release statuses. + status: [ReleaseStatus] + after: String + first: Int + ): ReleaseConnection +} + +`; + +exports[`schema.graphql 1`] = ` +# Schema +schema { + # Query and Mutation + query: Root + mutation: Mutation + + # Subscription + subscription: Subscription + +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Schema +schema { + # Query and Mutation + query: Root + mutation: Mutation + + # Subscription + subscription: Subscription +} + +`; diff --git a/tests/graphql_newline/__snapshots__/obj_type_def.graphql b/tests/graphql_newline/__snapshots__/obj_type_def.graphql new file mode 100644 index 000000000..19f699722 --- /dev/null +++ b/tests/graphql_newline/__snapshots__/obj_type_def.graphql @@ -0,0 +1,6 @@ +type Type { + id: ID + + name: String + +} diff --git a/tests/graphql_newline/directive_decl.graphql b/tests/graphql_newline/directive_decl.graphql new file mode 100644 index 000000000..cee085695 --- /dev/null +++ b/tests/graphql_newline/directive_decl.graphql @@ -0,0 +1,10 @@ +directive @dir( + # comment + arg1: String + + + # comment + arg2: String + arg3: String + +) on Field diff --git a/tests/graphql_newline/directives.graphql b/tests/graphql_newline/directives.graphql new file mode 100644 index 000000000..0829a33c7 --- /dev/null +++ b/tests/graphql_newline/directives.graphql @@ -0,0 +1,17 @@ +query MyQuery @directive( + arg: 5 + + # comment + arg2: 10 + +) { + field @skip( + if: true + + # comment + cursor: 10 + + ) @nope + otherField + ...fragmentSpread, @include(if: ["this isn't even a boolean", "wow, that's really odd",,,,,]) +} diff --git a/tests/graphql_newline/enum.graphql b/tests/graphql_newline/enum.graphql new file mode 100644 index 000000000..29ee21fa7 --- /dev/null +++ b/tests/graphql_newline/enum.graphql @@ -0,0 +1,11 @@ +enum State { + # pending state + PENDING + + # visible states + VISIBLE + INVISIBLE + + # archive state + ARCHIVED +} diff --git a/tests/graphql_newline/fields.graphql b/tests/graphql_newline/fields.graphql new file mode 100644 index 000000000..6541ac564 --- /dev/null +++ b/tests/graphql_newline/fields.graphql @@ -0,0 +1,35 @@ +query MyFirstQuery { + # comment + field { + + subfield + + # comment + subfield + + } + + field + #comment + field + +} + +mutation MyFirstMutation { + + # comment + name + + comment # comment + kind + +} + +subscription MySubscription { + + name + + comment + kind + +} diff --git a/tests/graphql_newline/input.graphql b/tests/graphql_newline/input.graphql new file mode 100644 index 000000000..d884414df --- /dev/null +++ b/tests/graphql_newline/input.graphql @@ -0,0 +1,8 @@ +input Params { + # Id + id: ID + + # Name + name: String + +} diff --git a/tests/graphql_newline/interface.graphql b/tests/graphql_newline/interface.graphql new file mode 100644 index 000000000..ca7c232c6 --- /dev/null +++ b/tests/graphql_newline/interface.graphql @@ -0,0 +1,9 @@ +interface Actor { + # Id + id: ID + + # Actor fields + name: String + kind: String + +} diff --git a/tests/graphql_newline/jsfmt.spec.js b/tests/graphql_newline/jsfmt.spec.js new file mode 100644 index 000000000..335646fb2 --- /dev/null +++ b/tests/graphql_newline/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname, { parser: "graphql" }); diff --git a/tests/graphql_newline/object_type_def.graphql b/tests/graphql_newline/object_type_def.graphql new file mode 100644 index 000000000..3f98df58b --- /dev/null +++ b/tests/graphql_newline/object_type_def.graphql @@ -0,0 +1,22 @@ +type Artist implements Node, Entity { + # The ID of an object + id: ID! + + # The MBID of the entity. + mbid: MBID! + + # A list of recordings linked to this entity. + recordings(after: String, first: Int): RecordingConnection + + # A list of releases linked to this entity. + releases( + # Filter by one or more release group types. + type: [ReleaseGroupType] + + # Filter by one or more release statuses. + status: [ReleaseStatus] + after: String + first: Int + ): ReleaseConnection + +} diff --git a/tests/graphql_newline/schema.graphql b/tests/graphql_newline/schema.graphql new file mode 100644 index 000000000..5f0591a5f --- /dev/null +++ b/tests/graphql_newline/schema.graphql @@ -0,0 +1,10 @@ +# Schema +schema { + # Query and Mutation + query: Root + mutation: Mutation + + # Subscription + subscription: Subscription + +} diff --git a/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap b/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap index 4a42bf04c..b350be039 100644 --- a/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap +++ b/tests/multiparser_js_graphql/__snapshots__/jsfmt.spec.js.snap @@ -89,6 +89,7 @@ const query = gql\` { user(id: 5) { firstName + lastName } }