Adds support for `getDefinitionAt` when called on a templateUrl property assignment. The currrent architecture for getting definitions is designed to be called on templates, so we have to introduce a new `getTsDefinitionAndBoundSpan` method to get Angular-specific definitions in TypeScript files and pass a `readTemplate` closure that will read the contents of a template using `TypeScriptServiceHost#getTemplates`. We can probably go in and make this nicer in a future PR, though I'm not sure what the best architecture should be yet. Part of angular/vscode-ng-language-service#111 PR Close #32238
		
			
				
	
	
		
			181 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import {ChildProcess, fork} from 'child_process';
 | 
						|
import {join} from 'path';
 | 
						|
import {goldenMatcher} from './matcher';
 | 
						|
import {Client} from './tsclient';
 | 
						|
 | 
						|
describe('Angular Language Service', () => {
 | 
						|
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; /* 10 seconds */
 | 
						|
  const PWD = process.env.PWD !;
 | 
						|
  const SERVER_PATH = './node_modules/typescript/lib/tsserver.js';
 | 
						|
  let server: ChildProcess;
 | 
						|
  let client: Client;
 | 
						|
 | 
						|
  beforeEach(() => {
 | 
						|
    jasmine.addMatchers(goldenMatcher);
 | 
						|
    server = fork(
 | 
						|
        SERVER_PATH,
 | 
						|
        [
 | 
						|
          '--logVerbosity',
 | 
						|
          'verbose',
 | 
						|
          '--logFile',
 | 
						|
          join(PWD, 'tsserver.log'),
 | 
						|
        ],
 | 
						|
        {
 | 
						|
          stdio: ['pipe', 'pipe', 'inherit', 'ipc'],
 | 
						|
        });
 | 
						|
    client = new Client(server);
 | 
						|
    client.listen();
 | 
						|
  });
 | 
						|
 | 
						|
  afterEach(async() => {
 | 
						|
    client.sendRequest('exit', {});
 | 
						|
 | 
						|
    // Give server process some time to flush all messages
 | 
						|
    await new Promise((resolve) => setTimeout(resolve, 1000));
 | 
						|
  });
 | 
						|
 | 
						|
  it('should be launched as tsserver plugin', async() => {
 | 
						|
    let response = await client.sendRequest('configure', {
 | 
						|
      hostInfo: 'vscode',
 | 
						|
    });
 | 
						|
    expect(response).toMatchGolden('configure.json');
 | 
						|
    response = await client.sendRequest('compilerOptionsForInferredProjects', {
 | 
						|
      'options': {
 | 
						|
        module: 'CommonJS',
 | 
						|
        target: 'ES6',
 | 
						|
        allowSyntheticDefaultImports: true,
 | 
						|
        allowNonTsExtensions: true,
 | 
						|
        allowJs: true,
 | 
						|
        jsx: 'Preserve'
 | 
						|
      }
 | 
						|
    });
 | 
						|
    expect(response).toMatchGolden('compilerOptionsForInferredProjects.json');
 | 
						|
    // Server does not send response to open request
 | 
						|
    // https://github.com/Microsoft/TypeScript/blob/master/lib/protocol.d.ts#L1055
 | 
						|
    client.sendRequest('open', {
 | 
						|
      file: `${PWD}/project/app/app.module.ts`,
 | 
						|
    });
 | 
						|
    // Server does not send response to geterr request
 | 
						|
    // https://github.com/Microsoft/TypeScript/blob/master/lib/protocol.d.ts#L1770
 | 
						|
    client.sendRequest('geterr', {delay: 0, files: [`${PWD}/project/app/app.module.ts`]});
 | 
						|
  });
 | 
						|
 | 
						|
  it('should perform completions', async() => {
 | 
						|
    await client.sendRequest('configure', {
 | 
						|
      hostInfo: 'vscode',
 | 
						|
    });
 | 
						|
    await client.sendRequest('compilerOptionsForInferredProjects', {
 | 
						|
      'options': {
 | 
						|
        module: 'CommonJS',
 | 
						|
        target: 'ES6',
 | 
						|
        allowSyntheticDefaultImports: true,
 | 
						|
        allowNonTsExtensions: true,
 | 
						|
        allowJs: true,
 | 
						|
        jsx: 'Preserve'
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    client.sendRequest('open', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
    });
 | 
						|
 | 
						|
    client.sendRequest('geterr', {delay: 0, files: [`${PWD}/project/app/app.component.ts`]});
 | 
						|
 | 
						|
    client.sendRequest('change', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      line: 5,
 | 
						|
      offset: 30,
 | 
						|
      endLine: 5,
 | 
						|
      endOffset: 30,
 | 
						|
      insertString: '.',
 | 
						|
    });
 | 
						|
 | 
						|
    const response = await client.sendRequest('completionInfo', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      line: 5,
 | 
						|
      offset: 31,
 | 
						|
    });
 | 
						|
    expect(response).toMatchGolden('completionInfo.json');
 | 
						|
  });
 | 
						|
 | 
						|
  it('should perform quickinfo', async() => {
 | 
						|
    client.sendRequest('open', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
    });
 | 
						|
 | 
						|
    const resp1 = await client.sendRequest('reload', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      tmpFile: `${PWD}/project/app/app.component.ts`,
 | 
						|
    }) as any;
 | 
						|
    expect(resp1.command).toBe('reload');
 | 
						|
    expect(resp1.success).toBe(true);
 | 
						|
 | 
						|
    const resp2 = await client.sendRequest('quickinfo', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      line: 5,
 | 
						|
      offset: 28,
 | 
						|
    });
 | 
						|
    expect(resp2).toMatchGolden('quickinfo.json');
 | 
						|
  });
 | 
						|
 | 
						|
  it('should perform definition', async() => {
 | 
						|
    client.sendRequest('open', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
    });
 | 
						|
 | 
						|
    const resp1 = await client.sendRequest('reload', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      tmpFile: `${PWD}/project/app/app.component.ts`,
 | 
						|
    }) as any;
 | 
						|
    expect(resp1.command).toBe('reload');
 | 
						|
    expect(resp1.success).toBe(true);
 | 
						|
 | 
						|
    const resp2 = await client.sendRequest('definition', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      line: 5,
 | 
						|
      offset: 28,
 | 
						|
    });
 | 
						|
    expect(resp2).toMatchGolden('definition.json');
 | 
						|
  });
 | 
						|
 | 
						|
  it('should perform definitionAndBoundSpan', async() => {
 | 
						|
    client.sendRequest('open', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
    });
 | 
						|
 | 
						|
    const resp1 = await client.sendRequest('reload', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      tmpFile: `${PWD}/project/app/app.component.ts`,
 | 
						|
    }) as any;
 | 
						|
    expect(resp1.command).toBe('reload');
 | 
						|
    expect(resp1.success).toBe(true);
 | 
						|
 | 
						|
    const resp2 = await client.sendRequest('definitionAndBoundSpan', {
 | 
						|
      file: `${PWD}/project/app/app.component.ts`,
 | 
						|
      line: 5,
 | 
						|
      offset: 28,
 | 
						|
    });
 | 
						|
    expect(resp2).toMatchGolden('definitionAndBoundSpan.json');
 | 
						|
  });
 | 
						|
 | 
						|
  it('should perform definitionAndBoundSpan for template URLs', async() => {
 | 
						|
    client.sendRequest('open', {
 | 
						|
      file: `${PWD}/project/app/widget.component.ts`,
 | 
						|
    });
 | 
						|
 | 
						|
    const resp1 = await client.sendRequest('reload', {
 | 
						|
      file: `${PWD}/project/app/widget.component.ts`,
 | 
						|
      tmpFile: `${PWD}/project/app/widget.component.ts`,
 | 
						|
    }) as any;
 | 
						|
    expect(resp1.command).toBe('reload');
 | 
						|
    expect(resp1.success).toBe(true);
 | 
						|
 | 
						|
    const resp2 = await client.sendRequest('definitionAndBoundSpan', {
 | 
						|
      file: `${PWD}/project/app/widget.component.ts`,
 | 
						|
      line: 5,
 | 
						|
      offset: 19,
 | 
						|
    });
 | 
						|
    expect(resp2).toMatchGolden('templateUrlDefinition.json');
 | 
						|
  });
 | 
						|
});
 |