Skip to content
This repository has been archived by the owner on Sep 27, 2023. It is now read-only.

Commit

Permalink
Merge pull request #83 from timjacobi/master
Browse files Browse the repository at this point in the history
support --noImplicitAny
  • Loading branch information
alloy committed Jan 9, 2019
2 parents b773504 + f8d8a87 commit 7f71c0d
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 6 deletions.
33 changes: 33 additions & 0 deletions src/addAnyTypeCast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as ts from "typescript";

export default function addAsAnyToObjectLiterals(oldSource: string): string {
function transformer<T extends ts.Node>(context: ts.TransformationContext) {
return function transform(rootNode: T) {
function visit(node: ts.Node): ts.Node {
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return ts.createAsExpression(
node as ts.Expression,
ts.createTypeReferenceNode("any", [])
);
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
}

const source = ts.createSourceFile(
"",
oldSource,
ts.ScriptTarget.ES2015,
true,
ts.ScriptKind.TS
);

const result = ts.transform(source, [transformer]);

const printer: ts.Printer = ts.createPrinter({
newLine: ts.NewLineKind.LineFeed
});
return printer.printFile(result.transformed[0] as ts.SourceFile);
}
13 changes: 11 additions & 2 deletions src/formatGeneratedModule.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { FormatModule } from "relay-compiler";
import * as ts from "typescript";
import addAnyTypeCast from "./addAnyTypeCast";

export const formatGeneratedModule: FormatModule = ({
export const formatterFactory = (
compilerOptions: ts.CompilerOptions = {}
): FormatModule => ({
moduleName,
documentType,
docText,
Expand All @@ -14,13 +18,18 @@ export const formatGeneratedModule: FormatModule = ({
? `import { ${documentType} } from "${relayRuntimeModule}";`
: "";
const docTextComment = docText ? "\n/*\n" + docText.trim() + "\n*/\n" : "";
let nodeStatement = `const node: ${documentType ||
"never"} = ${concreteText};`;
if (compilerOptions.noImplicitAny) {
nodeStatement = addAnyTypeCast(nodeStatement).trim();
}
return `/* tslint:disable */
${documentTypeImport}
${typeText || ""}
${docTextComment}
const node: ${documentType || "never"} = ${concreteText};
${nodeStatement}
(node as any).hash = '${sourceHash}';
export default node;
`;
Expand Down
5 changes: 3 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { PluginInterface } from "relay-compiler";

import { find } from "./FindGraphQLTags";
import { formatGeneratedModule } from "./formatGeneratedModule";
import { formatterFactory } from "./formatGeneratedModule";
import { loadCompilerOptions } from "./loadCompilerOptions";
import * as TypeScriptGenerator from "./TypeScriptGenerator";

export default function plugin(): PluginInterface {
return {
inputExtensions: ["ts", "tsx"],
outputExtension: "ts",
findGraphQLTags: find,
formatModule: formatGeneratedModule,
formatModule: formatterFactory(loadCompilerOptions()),
typeGenerator: TypeScriptGenerator
};
}
13 changes: 13 additions & 0 deletions src/loadCompilerOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as ts from "typescript";

export const loadCompilerOptions = (): ts.CompilerOptions => {
const configFileName = ts.findConfigFile(process.cwd(), ts.sys.fileExists);
if (!configFileName) {
return {};
}
const result = ts.readConfigFile(configFileName, ts.sys.readFile);
if (result.error) {
return {};
}
return result.config.compilerOptions;
};
9 changes: 9 additions & 0 deletions test/fixtures/generated-module/complete-example-no-cast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* tslint:disable */

import { ConcreteFragment } from "relay-runtime";
export type CompleteExample = { readonly id: string }


const node: ConcreteFragment = {"the":{"fragment":{"data":42}}};
(node as any).hash = 'edcba';
export default node;
2 changes: 1 addition & 1 deletion test/fixtures/generated-module/complete-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import { ConcreteFragment } from "relay-runtime";
export type CompleteExample = { readonly id: string }


const node: ConcreteFragment = {"the":{"fragment":{"data":42}}};
const node: ConcreteFragment = ({ "the": { "fragment": { "data": 42 } } } as any);
(node as any).hash = 'edcba';
export default node;
17 changes: 16 additions & 1 deletion test/formatGeneratedModule-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { join } from 'path'

import * as diff from 'jest-diff'

import { formatGeneratedModule } from '../src/formatGeneratedModule'
import { formatterFactory } from '../src/formatGeneratedModule'

expect.extend({
toMatchFile(received, fixturePath) {
Expand Down Expand Up @@ -37,6 +37,7 @@ expect.extend({

describe('formatGeneratedModule', () => {
it('works', () => {
const formatGeneratedModule = formatterFactory({noImplicitAny: true});
expect(formatGeneratedModule({
moduleName: 'complete-example',
documentType: 'ConcreteFragment',
Expand All @@ -50,6 +51,7 @@ describe('formatGeneratedModule', () => {
})

it('works without passing relay runtime module explicitly', () => {
const formatGeneratedModule = formatterFactory({noImplicitAny: true});
expect(formatGeneratedModule({
moduleName: 'complete-example',
documentType: 'ConcreteFragment',
Expand All @@ -60,4 +62,17 @@ describe('formatGeneratedModule', () => {
sourceHash: 'edcba',
})).toMatchFile(join(__dirname, 'fixtures/generated-module/complete-example.ts'))
})

it('doesn\'t add a typecast if noImplicitAny is not set', () => {
const formatGeneratedModule = formatterFactory();
expect(formatGeneratedModule({
moduleName: 'complete-example',
documentType: 'ConcreteFragment',
docText: null,
concreteText: JSON.stringify({ the: { fragment: { data: 42 } }}),
typeText: 'export type CompleteExample = { readonly id: string }',
hash: 'abcde',
sourceHash: 'edcba',
})).toMatchFile(join(__dirname, 'fixtures/generated-module/complete-example-no-cast.ts'))
})
})

0 comments on commit 7f71c0d

Please sign in to comment.