diff --git a/src/language/__tests__/parser-test.ts b/src/language/__tests__/parser-test.ts index 87e7b92c34..75ab51b1d7 100644 --- a/src/language/__tests__/parser-test.ts +++ b/src/language/__tests__/parser-test.ts @@ -84,6 +84,12 @@ describe('Parser', () => { `); }); + it('exposes the tokenCount', () => { + expect(parse('{ foo }').tokenCount).to.equal(3); + expect(parse('{ foo(bar: "baz") }').tokenCount).to.equal(8); + }); + + it('limit maximum number of tokens', () => { expect(() => parse('{ foo }', { maxTokens: 3 })).to.not.throw(); expect(() => parse('{ foo }', { maxTokens: 2 })).to.throw( diff --git a/src/language/ast.ts b/src/language/ast.ts index 29029342a1..6137eb6c1a 100644 --- a/src/language/ast.ts +++ b/src/language/ast.ts @@ -302,6 +302,7 @@ export interface DocumentNode { readonly kind: Kind.DOCUMENT; readonly loc?: Location; readonly definitions: ReadonlyArray; + readonly tokenCount?: number | undefined; } export type DefinitionNode = diff --git a/src/language/parser.ts b/src/language/parser.ts index eb54a0376b..03e4166210 100644 --- a/src/language/parser.ts +++ b/src/language/parser.ts @@ -114,7 +114,12 @@ export function parse( options?: ParseOptions | undefined, ): DocumentNode { const parser = new Parser(source, options); - return parser.parseDocument(); + const document = parser.parseDocument(); + Object.defineProperty(document, 'tokenCount', { + enumerable: false, + value: parser.tokenCount, + }); + return document; } /** @@ -198,6 +203,10 @@ export class Parser { this._tokenCounter = 0; } + get tokenCount(): number { + return this._tokenCounter; + } + /** * Converts a name lex token into a name parse node. */ @@ -1564,9 +1573,9 @@ export class Parser { const { maxTokens } = this._options; const token = this._lexer.advance(); - if (maxTokens !== undefined && token.kind !== TokenKind.EOF) { + if (token.kind !== TokenKind.EOF) { ++this._tokenCounter; - if (this._tokenCounter > maxTokens) { + if (maxTokens !== undefined && this._tokenCounter > maxTokens) { throw syntaxError( this._lexer.source, token.start,