diff --git a/src/language/__tests__/parser-test.ts b/src/language/__tests__/parser-test.ts index 71efd7b8eb..d98b6a6f41 100644 --- a/src/language/__tests__/parser-test.ts +++ b/src/language/__tests__/parser-test.ts @@ -100,6 +100,11 @@ describe('Parser', () => { ); }); + it('exposes the tokenCount', () => { + expect(parse('{ foo }').tokenCount).to.equal(3); + expect(parse('{ foo(bar: "baz") }').tokenCount).to.equal(8); + }); + it('parses variable inline values', () => { expect(() => parse('{ field(complex: { a: { b: [ $var ] } }) }'), diff --git a/src/language/ast.ts b/src/language/ast.ts index e7ea84fd79..e10a4fe119 100644 --- a/src/language/ast.ts +++ b/src/language/ast.ts @@ -312,6 +312,7 @@ export interface DocumentNode { readonly kind: Kind.DOCUMENT; readonly loc?: Location | undefined; readonly definitions: ReadonlyArray; + readonly tokenCount?: number | undefined; } export type DefinitionNode = diff --git a/src/language/parser.ts b/src/language/parser.ts index 5e70bcb9f0..3d2018ba4b 100644 --- a/src/language/parser.ts +++ b/src/language/parser.ts @@ -119,7 +119,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; } /** @@ -201,6 +206,10 @@ export class Parser { this._tokenCounter = 0; } + get tokenCount(): number { + return this._tokenCounter; + } + /** * Converts a name lex token into a name parse node. */ @@ -1601,9 +1610,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,