Path: blob/main/extensions/copilot/src/platform/parser/test/node/parser.spec.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { afterAll, expect, suite, test } from 'vitest';7import { _getDocumentableNodeIfOnIdentifier } from '../../node/docGenParsing';8import { _getCoarseParentScope, } from '../../node/parserImpl';9import { _dispose, _parse } from '../../node/parserWithCaching';10import { WASMLanguage } from '../../node/treeSitterLanguages';11import { allKnownQueries } from '../../node/treeSitterQueries';12import { insertRangeMarkers } from './markers';1314suite('getDocumentableNodeIfOnIdentifier', () => {15// TODO@ulugbekna: rewrite all tests using insertRangeMarkers for better visualization1617test('should return undefined for range not containing an identifier', async () => {18const result = await _getDocumentableNodeIfOnIdentifier(19WASMLanguage.TypeScript,20'const x = 1;',21{22startIndex: 0,23endIndex: 0,24}25);26expect(result).toBeUndefined();27});2829test('should return object for range containing an identifier not in a definition or declaration', async () => {30const result = await _getDocumentableNodeIfOnIdentifier(31WASMLanguage.TypeScript,32'const x = 1;',33{34startIndex: 6,35endIndex: 7,36}37);38expect(result).toMatchInlineSnapshot(`39{40"identifier": "x",41"nodeRange": {42"endIndex": 11,43"startIndex": 6,44},45}46`);47expect(48insertRangeMarkers('const x = 1;', [result?.nodeRange!])49).toMatchInlineSnapshot(50`"const <>x = 1</>;"`51);52});5354test('should return the identifier and node range for a range containing an identifier in a definition', async () => {55const result = await _getDocumentableNodeIfOnIdentifier(56WASMLanguage.TypeScript,57'function foo() {}',58{ startIndex: 9, endIndex: 12 }59);60expect(result).toMatchInlineSnapshot(`61{62"identifier": "foo",63"nodeRange": {64"endIndex": 17,65"startIndex": 0,66},67}68`);69expect(70insertRangeMarkers('function foo() {}', [result?.nodeRange!])71).toMatchInlineSnapshot(`"<>function foo() {}</>"`);72});7374test('should return the identifier and node range for a range containing an identifier in a declaration', async () => {75const result = await _getDocumentableNodeIfOnIdentifier(76WASMLanguage.TypeScript,77'const x = 1;',78{79startIndex: 6,80endIndex: 7,81}82);83expect(result).toMatchInlineSnapshot(`84{85"identifier": "x",86"nodeRange": {87"endIndex": 11,88"startIndex": 6,89},90}91`);92});9394test('should return the identifier and node range for a range containing an identifier in a var spec', async () => {95const result = await _getDocumentableNodeIfOnIdentifier(96WASMLanguage.TypeScript,97'var x: number;',98{ startIndex: 4, endIndex: 5 }99);100expect(result).toMatchInlineSnapshot(`101{102"identifier": "x",103"nodeRange": {104"endIndex": 13,105"startIndex": 4,106},107}108`);109});110});111112suite('getParentScope', () => {113test('Finding parent node in TypeScript', async () => {114const result = await _getCoarseParentScope(115WASMLanguage.TypeScript,116[117'interface IFar {',118' bar(): void;',119' foo(): void;',120'}'121].join('\n'),122{ startPosition: { row: 1, column: 2 }, endPosition: { row: 1, column: 5 } }123);124expect(result).toStrictEqual({125startPosition: { row: 0, column: 0 },126endPosition: { row: 3, column: 1 },127});128});129130test('Finding parent node in Python', async () => {131const result = await _getCoarseParentScope(132WASMLanguage.Python,133[134'# some comment',135'class Room:',136' length = 0.0',137' breadth = 0.0',138' def Area(abc):',139' print("The area is " + length*breadth)',140'',141'# some other comment',142].join('\n'),143{144startPosition: { row: 5, column: 5 },145endPosition: { row: 5, column: 5 },146}147);148expect(result).toStrictEqual({149startPosition: { row: 4, column: 3 },150endPosition: { row: 5, column: 44 },151});152});153154test('Finding parent node in Java', async () => {155const result = await _getCoarseParentScope(156WASMLanguage.Java,157[158'/*** comment',159'',160' comment ***/ ',161'public class Main {',162' public static void main(String[] args) {',163' System.out.println("Hello World");',164' }',165'}',166].join('\n'),167{168startPosition: { row: 5, column: 5 },169endPosition: { row: 5, column: 5 },170}171);172expect(result).toStrictEqual({173startPosition: { row: 4, column: 1 },174endPosition: { row: 6, column: 2 },175});176});177});178179180suite('All Tree Sitter Queries are valid', () => {181182afterAll(() => _dispose());183184for (const language in allKnownQueries) {185generateTest(language as WASMLanguage);186}187188function generateTest(language: WASMLanguage) {189test(`Valid queries for ${language}`, async () => {190const queries = allKnownQueries[language];191const parseTreeRef = await _parse(language, '');192try {193const lang = parseTreeRef.tree.getLanguage();194for (const query of queries) {195try {196lang.query(query);197} catch (err) {198assert.fail(`Query failed for ${query}: ${err}`);199}200}201} finally {202parseTreeRef.dispose();203}204});205}206});207208209