Andrew Scott 459af57a31 refactor(compiler-cli): Adjust generated TCB when checkTypeOfPipes is false (#40523)
When `checkTypeOfPipes` is set to `false`, our TCB currently generates
the a statement like the following when pipes appear in the template:
`(_pipe1 as any).transform(args)`

This did enable us to get _some_ information from the Language Service
about pipes in this case because we still had access to the pipe
instance. However, because it is immediately cast to `any`, we cannot
get type information about the transform access. That means actions like "go to
definition", "find references", "quick info", etc. will return
incomplete information or fail altogether.

Instead, this commit changes the TCB to generate `(_pipe1.transform as any)(args)`.
This gives us the ability to get complete information for the LS
operations listed above.

PR Close #40523
2021-05-06 17:54:14 -04:00

87 lines
2.9 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {initMockFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/testing';
import * as ts from 'typescript';
import {LanguageServiceTestEnv, OpenBuffer, Project} from '../testing';
import {collectMemberMethods, findTightestNode} from '../ts_utils';
describe('ts utils', () => {
describe('collectMemberMethods', () => {
beforeEach(() => {
initMockFileSystem('Native');
});
it('gets only methods in class, not getters, setters, or properties', () => {
const files = {
'app.ts': `
export class AppCmp {
prop!: string;
get myString(): string {
return '';
}
set myString(v: string) {
}
one() {}
two() {}
}`,
};
const env = LanguageServiceTestEnv.setup();
const project = env.addProject('test', files);
const appFile = project.openFile('app.ts');
appFile.moveCursorToText('AppC¦mp');
const memberMethods = getMemberMethodNames(project, appFile);
expect(memberMethods).toEqual(['one', 'two']);
});
it('gets inherited methods in class', () => {
const files = {
'app.ts': `
export class BaseClass {
baseMethod() {}
}
export class AppCmp extends BaseClass {}`,
};
const env = LanguageServiceTestEnv.setup();
const project = env.addProject('test', files);
const appFile = project.openFile('app.ts');
appFile.moveCursorToText('AppC¦mp');
const memberMethods = getMemberMethodNames(project, appFile);
expect(memberMethods).toEqual(['baseMethod']);
});
it('does not return duplicates if base method is overridden', () => {
const files = {
'app.ts': `
export class BaseClass {
baseMethod() {}
}
export class AppCmp extends BaseClass {
baseMethod() {}
}`,
};
const env = LanguageServiceTestEnv.setup();
const project = env.addProject('test', files);
const appFile = project.openFile('app.ts');
appFile.moveCursorToText('AppC¦mp');
const memberMethods = getMemberMethodNames(project, appFile);
expect(memberMethods).toEqual(['baseMethod']);
});
function getMemberMethodNames(project: Project, file: OpenBuffer): string[] {
const sf = project.getSourceFile('app.ts')!;
const node = findTightestNode(sf, file.cursor)!;
expect(ts.isClassDeclaration(node.parent)).toBe(true);
return collectMemberMethods(node.parent as ts.ClassDeclaration, project.getTypeChecker())
.map(m => m.name.getText())
.sort();
}
});
});