Skip to content

Commit 58f07c4

Browse files
authored
[Scala] Fix naming conflicts and update API references (#402)
* [Scala] Fix naming conflicts and update API references Fixes #357 * Convert generator to use TypeScript * Add unit tests for emitting package declaration * Move test into separate group * Emit js.UndefOr for optional input object types * Fix parameter section generation * Update input object test snapshot
1 parent 7723fcd commit 58f07c4

13 files changed

Lines changed: 475 additions & 390 deletions

File tree

src/generate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export default function generate(
103103
output = generateFlowSource(context);
104104
break;
105105
case 'scala':
106-
output = generateScalaSource(context, options);
106+
output = generateScalaSource(context);
107107
}
108108

109109
if (outputPath) {
Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,21 @@ import {
22
GraphQLError,
33
getNamedType,
44
isCompositeType,
5-
isAbstractType,
6-
isEqualType,
7-
GraphQLScalarType,
85
GraphQLEnumType,
9-
GraphQLList,
106
GraphQLNonNull,
11-
GraphQLID,
127
GraphQLInputObjectType
138
} from 'graphql'
149

1510
import { isTypeProperSuperTypeOf } from '../utilities/graphql'
1611

1712
import {
1813
join,
19-
wrap,
2014
} from '../utilities/printing';
2115

2216
import {
2317
packageDeclaration,
2418
objectDeclaration,
2519
caseClassDeclaration,
26-
propertyDeclaration,
27-
propertyDeclarations,
2820
escapeIdentifierIfNeeded,
2921
comment
3022
} from './language';
@@ -35,16 +27,12 @@ import {
3527
caseClassNameForInlineFragment,
3628
operationClassName,
3729
enumCaseName,
38-
propertiesFromSelectionSet,
39-
propertyFromField,
40-
propertyFromInlineFragment,
41-
propertyFromFragmentSpread
30+
propertyFromLegacyField,
31+
propertyFromInputField,
4232
} from './naming';
4333

4434
import {
45-
escapedString,
4635
multilineString,
47-
dictionaryLiteralForFieldArguments,
4836
} from './values';
4937

5038
import {
@@ -53,15 +41,19 @@ import {
5341
} from './types';
5442

5543
import CodeGenerator from '../utilities/CodeGenerator';
44+
import { LegacyCompilerContext, LegacyOperation, LegacyFragment, LegacyField, LegacyInlineFragment } from '../compiler/legacyIR';
45+
import { GraphQLType } from 'graphql';
46+
import { Property } from './language';
47+
import { GraphQLCompositeType } from 'graphql';
5648

57-
export function generateSource(context, options) {
49+
export function generateSource(context: LegacyCompilerContext) {
5850
const generator = new CodeGenerator(context);
5951

6052
generator.printOnNewline('// This file was automatically generated and should not be edited.');
6153
generator.printNewline();
6254

63-
if (context.namespace) {
64-
packageDeclaration(generator, context.namespace);
55+
if (context.options.namespace) {
56+
packageDeclaration(generator, context.options.namespace);
6557
}
6658

6759
context.typesUsed.forEach(type => {
@@ -80,7 +72,7 @@ export function generateSource(context, options) {
8072
}
8173

8274
export function classDeclarationForOperation(
83-
generator,
75+
generator: CodeGenerator<LegacyCompilerContext, any>,
8476
{
8577
operationName,
8678
operationType,
@@ -91,9 +83,8 @@ export function classDeclarationForOperation(
9183
fragmentSpreads,
9284
fragmentsReferenced,
9385
source,
94-
sourceWithFragments,
9586
operationId
96-
}
87+
}: LegacyOperation
9788
) {
9889
let objectName;
9990
let protocol;
@@ -113,8 +104,7 @@ export function classDeclarationForOperation(
113104

114105
objectDeclaration(generator, {
115106
objectName,
116-
modifiers: [],
117-
superclass: protocol
107+
superclass: protocol,
118108
}, () => {
119109
if (source) {
120110
generator.printOnNewline('val operationString =');
@@ -123,7 +113,9 @@ export function classDeclarationForOperation(
123113
});
124114
}
125115

126-
operationIdentifier(generator, { operationName, sourceWithFragments, operationId });
116+
if (operationId) {
117+
operationIdentifier(generator, operationId);
118+
}
127119

128120
if (fragmentsReferenced && fragmentsReferenced.length > 0) {
129121
generator.printNewlineIfNeeded();
@@ -144,7 +136,7 @@ export function classDeclarationForOperation(
144136
const properties = variables.map(({ name, type }) => {
145137
const propertyName = escapeIdentifierIfNeeded(name);
146138
const typeName = typeNameFromGraphQLType(generator.context, type);
147-
const isOptional = !(type instanceof GraphQLNonNull || type.ofType instanceof GraphQLNonNull);
139+
const isOptional = !(type instanceof GraphQLNonNull || type instanceof GraphQLNonNull);
148140
return { name, propertyName, type, typeName, isOptional };
149141
});
150142

@@ -172,15 +164,15 @@ export function classDeclarationForOperation(
172164
}
173165

174166
export function caseClassDeclarationForFragment(
175-
generator,
167+
generator: CodeGenerator<LegacyCompilerContext, any>,
176168
{
177169
fragmentName,
178170
typeCondition,
179171
fields,
180172
inlineFragments,
181173
fragmentSpreads,
182174
source
183-
}
175+
}: LegacyFragment
184176
) {
185177
const caseClassName = caseClassNameForFragmentName(fragmentName);
186178

@@ -190,7 +182,7 @@ export function caseClassDeclarationForFragment(
190182
fields,
191183
inlineFragments,
192184
fragmentSpreads
193-
}, () => {}, () => {
185+
}, () => {
194186
if (source) {
195187
generator.printOnNewline('val fragmentString =');
196188
generator.withIndent(() => {
@@ -201,25 +193,32 @@ export function caseClassDeclarationForFragment(
201193
}
202194

203195
export function caseClassDeclarationForSelectionSet(
204-
generator,
196+
generator: CodeGenerator<LegacyCompilerContext, any>,
205197
{
206198
caseClassName,
207199
parentType,
208200
fields,
209201
inlineFragments,
210202
fragmentSpreads,
211203
viewableAs
204+
}: {
205+
caseClassName: string,
206+
parentType: GraphQLCompositeType,
207+
fields: LegacyField[],
208+
inlineFragments?: LegacyInlineFragment[],
209+
fragmentSpreads?: string[],
210+
viewableAs?: {
211+
caseClassName: string,
212+
properties: (LegacyField & Property)[]
213+
}
212214
},
213-
beforeClosure,
214-
objectClosure,
215+
objectClosure?: () => void,
215216
) {
216217
const possibleTypes = parentType ? possibleTypesForType(generator.context, parentType) : null;
217218

218-
let properties;
219-
220219
if (!possibleTypes || possibleTypes.length == 1) {
221-
properties = fields
222-
.map(field => propertyFromField(generator.context, field))
220+
const properties = fields
221+
.map(field => propertyFromLegacyField(generator.context, field, caseClassName))
223222
.filter(field => field.propertyName != "__typename");
224223

225224
caseClassDeclaration(generator, { caseClassName, params: properties.map(p => {
@@ -231,22 +230,22 @@ export function caseClassDeclarationForSelectionSet(
231230
} else {
232231
generator.printNewlineIfNeeded();
233232
const properties = fields
234-
.map(field => propertyFromField(generator.context, field))
233+
.map(field => propertyFromLegacyField(generator.context, field, caseClassName))
235234
.filter(field => field.propertyName != "__typename");
236235

237236
caseClassDeclaration(generator, { caseClassName, params: properties.map(p => {
238237
return {
239238
name: p.responseName,
240239
type: p.typeName,
241240
};
242-
}), superclass: 'me.shadaj.slinky.core.WithRaw'}, () => {
241+
}), superclass: 'slinky.readwrite.WithRaw'}, () => {
243242
if (inlineFragments && inlineFragments.length > 0) {
244243
inlineFragments.forEach((inlineFragment) => {
245244
const fragClass = caseClassNameForInlineFragment(inlineFragment);
246245
generator.printOnNewline(`def as${inlineFragment.typeCondition}`);
247246
generator.print(`: Option[${fragClass}] =`);
248247
generator.withinBlock(() => {
249-
generator.printOnNewline(`if (${fragClass}.possibleTypes.contains(this.raw.__typename.asInstanceOf[String])) Some(implicitly[me.shadaj.slinky.core.Reader[${fragClass}]].read(this.raw)) else None`);
248+
generator.printOnNewline(`if (${fragClass}.possibleTypes.contains(this.raw.__typename.asInstanceOf[String])) Some(implicitly[slinky.readwrite.Reader[${fragClass}]].read(this.raw)) else None`);
250249
});
251250
});
252251
}
@@ -259,7 +258,7 @@ export function caseClassDeclarationForSelectionSet(
259258
generator.printOnNewline(`def as${s}`);
260259
generator.print(`: Option[${s}] =`);
261260
generator.withinBlock(() => {
262-
generator.printOnNewline(`if (${s}.possibleTypes.contains(this.raw.__typename.asInstanceOf[String])) Some(implicitly[me.shadaj.slinky.core.Reader[${s}]].read(this.raw)) else None`);
261+
generator.printOnNewline(`if (${s}.possibleTypes.contains(this.raw.__typename.asInstanceOf[String])) Some(implicitly[slinky.readwrite.Reader[${s}]].read(this.raw)) else None`);
263262
});
264263
}
265264
})
@@ -275,7 +274,7 @@ export function caseClassDeclarationForSelectionSet(
275274
caseClassName: caseClassNameForInlineFragment(inlineFragment),
276275
parentType: inlineFragment.typeCondition,
277276
fields: inlineFragment.fields,
278-
inlineFragments: inlineFragment.inlineFragments,
277+
// inlineFragments: inlineFragment.inlineFragments,
279278
fragmentSpreads: inlineFragment.fragmentSpreads,
280279
viewableAs: {
281280
caseClassName,
@@ -309,43 +308,43 @@ export function caseClassDeclarationForSelectionSet(
309308
})
310309
}
311310

311+
fields.filter(field => isCompositeType(getNamedType(field.type))).forEach(field => {
312+
caseClassDeclarationForSelectionSet(
313+
generator,
314+
{
315+
caseClassName: caseClassNameForPropertyName(field.responseName),
316+
parentType: getNamedType(field.type) as GraphQLCompositeType,
317+
fields: field.fields || [],
318+
inlineFragments: field.inlineFragments,
319+
fragmentSpreads: field.fragmentSpreads
320+
}
321+
);
322+
});
323+
312324
if (objectClosure) {
313325
objectClosure();
314326
}
315327
});
316-
317-
fields.filter(field => isCompositeType(getNamedType(field.type))).forEach(field => {
318-
caseClassDeclarationForSelectionSet(
319-
generator,
320-
{
321-
caseClassName: caseClassNameForPropertyName(field.responseName),
322-
parentType: getNamedType(field.type),
323-
fields: field.fields,
324-
inlineFragments: field.inlineFragments,
325-
fragmentSpreads: field.fragmentSpreads
326-
}
327-
);
328-
});
329328
}
330329

331-
function operationIdentifier(generator, { operationName, sourceWithFragments, operationId }) {
332-
if (!generator.context.generateOperationIds) {
330+
function operationIdentifier(generator: CodeGenerator<LegacyCompilerContext, any>, operationId: string) {
331+
if (!generator.context.options.generateOperationIds) {
333332
return
334333
}
335334

336335
generator.printNewlineIfNeeded();
337336
generator.printOnNewline(`val operationIdentifier: String = "${operationId}"`);
338337
}
339338

340-
export function typeDeclarationForGraphQLType(generator, type) {
339+
export function typeDeclarationForGraphQLType(generator: CodeGenerator<LegacyCompilerContext, any>, type: GraphQLType) {
341340
if (type instanceof GraphQLEnumType) {
342341
enumerationDeclaration(generator, type);
343342
} else if (type instanceof GraphQLInputObjectType) {
344343
caseClassDeclarationForInputObjectType(generator, type);
345344
}
346345
}
347346

348-
function enumerationDeclaration(generator, type) {
347+
function enumerationDeclaration(generator: CodeGenerator<LegacyCompilerContext, any>, type: GraphQLEnumType) {
349348
const { name, description } = type;
350349
const values = type.getValues();
351350

@@ -361,15 +360,16 @@ function enumerationDeclaration(generator, type) {
361360
generator.printNewline();
362361
}
363362

364-
function caseClassDeclarationForInputObjectType(generator, type) {
363+
function caseClassDeclarationForInputObjectType(generator: CodeGenerator<LegacyCompilerContext, any>, type: GraphQLInputObjectType) {
365364
const { name: caseClassName, description } = type;
366365
const fields = Object.values(type.getFields());
367-
const properties = fields.map(field => propertyFromField(generator.context, field));
366+
const properties = fields.map(field => propertyFromInputField(generator.context, field, generator.context.options.namespace));
368367

369368
caseClassDeclaration(generator, { caseClassName, description, params: properties.map(p => {
370369
return {
371370
name: p.propertyName,
372-
type: p.typeName
371+
type: p.typeName,
372+
defaultValue: p.isOptional ? "scala.scalajs.js.undefined" : ""
373373
};
374374
})}, () => {});
375375
}
File renamed without changes.

src/scala/language.js

Lines changed: 0 additions & 66 deletions
This file was deleted.

0 commit comments

Comments
 (0)