Skip to content

Commit

Permalink
feat: add gql call expressions support (#2509)
Browse files Browse the repository at this point in the history
Add ```gql(``)```, ```graphql(``)``` call expressions support for highlighting & language support

- adds highlighting to grammar
- create simper unit tests for just `findGraphQLTags`
- removes some complex and seemingly unused legacy relay-related behaviour from `findGraphQLTags`. If you have any cases where graphql language support disappears with a nested graphql template tag/etc that worked before this, please let us know!

Co-authored-by: Rikki Schulte <rikki.schulte@gmail.com>
  • Loading branch information
Chnapy and acao authored Jul 3, 2022
1 parent 74aac2c commit 737d418
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 97 deletions.
7 changes: 7 additions & 0 deletions .changeset/three-rice-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'vscode-graphql': patch
'graphql-language-service-server': patch
'graphql-language-service-cli': patch
---

Add ```gql(``)```, ```graphql(``)``` call expressions support for highlighting & language
1 change: 1 addition & 0 deletions custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,4 @@ runtimes
typeahead
typeaheads
unparsable
randomthing
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"build:packages": "yarn tsc",
"build:watch": "yarn tsc --watch",
"watch": "yarn build:watch",
"watch-vscode": "concurrently --raw 'yarn tsc --watch' 'yarn workspace vscode-graphql run compile --watch'",
"watch-vscode": "concurrently --raw \"yarn tsc --watch\" \"yarn workspace vscode-graphql run compile --watch\"",
"check": "yarn tsc --dry",
"cypress-open": "yarn workspace graphiql cypress-open",
"dev-graphiql": "yarn workspace graphiql dev",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,36 @@ query Test {
`);
});

it('parseDocument finds queries in call expressions with template literals', async () => {
const text = `
// @flow
import {gql} from 'react-apollo';
import type {B} from 'B';
import A from './A';
const QUERY = gql(\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`);
export function Example(arg: string) {}`;

const contents = parseDocument(text, 'test.js');
expect(contents[0].query).toEqual(`
query Test {
test {
value
...FragmentsComment
}
}
`);
});

it('parseDocument finds queries in #graphql-annotated templates', async () => {
const text = `
import {gql} from 'react-apollo';
Expand Down Expand Up @@ -638,6 +668,29 @@ query Test {
\${A.fragments.test}
\`
export function Example(arg: string) {}`;

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

it('parseDocument ignores non gql call expressions with template literals', async () => {
const text = `
// @flow
import randomthing from 'package';
import type {B} from 'B';
import A from './A';
const QUERY = randomthing(\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`);
export function Example(arg: string) {}`;

const contents = parseDocument(text, 'test.js');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/**
* Copyright (c) 2022 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import { tmpdir } from 'os';

import { findGraphQLTags as baseFindGraphQLTags } from '../findGraphQLTags';

jest.mock('../Logger');

import { Logger } from '../Logger';

describe('findGraphQLTags', () => {
const logger = new Logger(tmpdir());
const findGraphQLTags = (text: string, ext: string) =>
baseFindGraphQLTags(text, ext, '', logger);

it('finds queries in tagged templates', async () => {
const text = `
// @flow
import {gql} from 'react-apollo';
import type {B} from 'B';
import A from './A';
const QUERY = gql\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`
export function Example(arg: string) {}`;

const contents = findGraphQLTags(text, '.js');
expect(contents[0].template).toEqual(`
query Test {
test {
value
...FragmentsComment
}
}
`);
});

it('finds queries in call expressions with template literals', async () => {
const text = `
// @flow
import {gql} from 'react-apollo';
import type {B} from 'B';
import A from './A';
const QUERY = gql(\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`);
export function Example(arg: string) {}`;

const contents = findGraphQLTags(text, '.js');
expect(contents[0].template).toEqual(`
query Test {
test {
value
...FragmentsComment
}
}
`);
});

it('finds queries in #graphql-annotated templates', async () => {
const text = `
import {gql} from 'react-apollo';
import {B} from 'B';
import A from './A';
const QUERY: string = \`#graphql
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`
export function Example(arg: string) {}`;

const contents = findGraphQLTags(text, '.ts');
expect(contents[0].template).toEqual(`#graphql
query Test {
test {
value
...FragmentsComment
}
}
`);
});

it('finds queries in /* GraphQL */ prefixed templates', async () => {
const text = `
import {gql} from 'react-apollo';
import {B} from 'B';
import A from './A';
const QUERY: string =
/* GraphQL */
\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`
export function Example(arg: string) {}`;

const contents = findGraphQLTags(text, '.ts');
expect(contents[0].template).toEqual(`
query Test {
test {
value
...FragmentsComment
}
}
`);
});

it('finds queries with nested template tag expressions', async () => {
const text = `export default {
else: () => gql\` query {} \`
}`;

const contents = findGraphQLTags(text, '.ts');
expect(contents[0].template).toEqual(` query {} `);
});

it('finds queries with template tags inside call expressions', async () => {
const text = `something({
else: () => gql\` query {} \`
})`;

const contents = findGraphQLTags(text, '.ts');
expect(contents[0].template).toEqual(` query {} `);
});

it('ignores non gql tagged templates', async () => {
const text = `
// @flow
import randomthing from 'package';
import type {B} from 'B';
import A from './A';
const QUERY = randomthing\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`
export function Example(arg: string) {}`;

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

it('ignores non gql call expressions with template literals', async () => {
const text = `
// @flow
import randomthing from 'package';
import type {B} from 'B';
import A from './A';
const QUERY = randomthing(\`
query Test {
test {
value
...FragmentsComment
}
}
\${A.fragments.test}
\`);
export function Example(arg: string) {}`;

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

0 comments on commit 737d418

Please sign in to comment.