Skip to content

Commit

Permalink
Adds better error messages for unparsable babel files: (#2175)
Browse files Browse the repository at this point in the history
  • Loading branch information
orta committed Feb 18, 2022
1 parent d3b1540 commit 48c5df6
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 6 deletions.
6 changes: 6 additions & 0 deletions .changeset/ten-pianos-report.md
@@ -0,0 +1,6 @@
---
"graphql-language-service-server": patch
"graphql-language-service": patch
---

Better handling of unparsable babel JS/TS files
Expand Up @@ -127,7 +127,7 @@ export class MessageProcessor {
this._graphQLConfig = config;
this._parser = (text, uri) => {
const p = parser ?? parseDocument;
return p(text, uri, fileExtensions, graphqlFileExtensions);
return p(text, uri, fileExtensions, graphqlFileExtensions, this._logger);
};
this._tmpDir = tmpDir || tmpdir();
this._tmpDirBase = path.join(this._tmpDir, 'graphql-language-service');
Expand Down
Expand Up @@ -623,6 +623,26 @@ export function Example(arg: string) {}`;
expect(contents.length).toEqual(0);
});

it('an unparsable JS/TS file does not throw and bring down the server', async () => {
const text = `
// @flow
import type randomthing fro 'package';
import type {B} from 'B';
im port A from './A';
con QUERY = randomthing\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.frag`;

const contents = parseDocument(text, 'test.js');
expect(contents.length).toEqual(0);
});

describe('handleWatchedFilesChangedNotification', () => {
const mockReadFileSync: jest.Mock = jest.requireMock('fs').readFileSync;

Expand Down
25 changes: 22 additions & 3 deletions packages/graphql-language-service-server/src/findGraphQLTags.ts
Expand Up @@ -17,6 +17,7 @@ import {
import { Position, Range } from 'graphql-language-service-utils';

import { parse, ParserOptions, ParserPlugin } from '@babel/parser';
import { Logger } from './Logger';

// Attempt to be as inclusive as possible of source text.
const PARSER_OPTIONS: ParserOptions = {
Expand Down Expand Up @@ -68,18 +69,36 @@ const BABEL_PLUGINS: ParserPlugin[] = [
'logicalAssignment',
];

export function findGraphQLTags(text: string, ext: string): TagResult[] {
export function findGraphQLTags(
text: string,
ext: string,
uri: string,
logger: Logger,
): TagResult[] {
const result: TagResult[] = [];

const plugins = BABEL_PLUGINS.slice(0, BABEL_PLUGINS.length);

if (ext === '.ts' || ext === '.tsx') {
const isTypeScript = ext === '.ts' || ext === '.tsx';
if (isTypeScript) {
plugins?.push('typescript');
} else {
plugins?.push('flow', 'flowComments');
}
PARSER_OPTIONS.plugins = plugins;
const ast = parse(text, PARSER_OPTIONS);

let parsedAST: ReturnType<typeof parse> | undefined = undefined;
try {
parsedAST = parse(text, PARSER_OPTIONS);
} catch (error) {
const type = isTypeScript ? 'TypeScript' : 'JavaScript';
logger.error(
`Could not parse the ${type} file at ${uri} to extract the graphql tags:`,
);
logger.error(error);
return [];
}
const ast = parsedAST!;

const visitors = {
CallExpression: (node: Expression) => {
Expand Down
6 changes: 4 additions & 2 deletions packages/graphql-language-service-server/src/parseDocument.ts
Expand Up @@ -3,6 +3,7 @@ import type { CachedContent } from 'graphql-language-service';
import { Range, Position } from 'graphql-language-service-utils';

import { findGraphQLTags, DEFAULT_TAGS } from './findGraphQLTags';
import { Logger } from './Logger';

export const DEFAULT_SUPPORTED_EXTENSIONS = [
'.js',
Expand All @@ -17,7 +18,7 @@ export const DEFAULT_SUPPORTED_EXTENSIONS = [
];

/**
* .graphql is the officially reccomended extension for graphql files
* .graphql is the officially recommended extension for graphql files
*
* .gql and .graphqls are included for compatibility for commonly used extensions
*
Expand All @@ -43,6 +44,7 @@ export function parseDocument(
uri: string,
fileExtensions: string[] = DEFAULT_SUPPORTED_EXTENSIONS,
graphQLFileExtensions: string[] = DEFAULT_SUPPORTED_GRAPHQL_EXTENSIONS,
logger: Logger = new Logger(),
): CachedContent[] {
// Check if the text content includes a GraphQLV query.
// If the text doesn't include GraphQL queries, do not proceed.
Expand All @@ -51,7 +53,7 @@ export function parseDocument(
if (DEFAULT_TAGS.some(t => t === text)) {
return [];
}
const templates = findGraphQLTags(text, ext);
const templates = findGraphQLTags(text, ext, uri, logger);
return templates.map(({ template, range }) => ({ query: template, range }));
}
if (graphQLFileExtensions.some(e => e === ext)) {
Expand Down

2 comments on commit 48c5df6

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.