refactor(language-service): Consistent naming between ts and ng LanguageService (#34888)

This commit makes the Angular Language Service interface a strict subset
of TypeScript's Language Service by renaming all methods to be
consistent with TypeScript's.

The custom Angular `LanguageService` interface was needed before the
inception of TypeScript tsserver plugin, but is now obsolete since
Angular LS is a proper tsserver plugin.

This allows us to easily adapt to upstream TS changes in the future, and
also allows us to reuse all data types defined in TypeScript.

PR Close #34888
This commit is contained in:
Keen Yee Liau 2020-01-21 14:51:43 -08:00 committed by Matias Niemelä
parent 84d24c08e1
commit f723a27a71
8 changed files with 189 additions and 221 deletions

View File

@ -12,7 +12,7 @@ import {getTemplateCompletions} from './completions';
import {getDefinitionAndBoundSpan, getTsDefinitionAndBoundSpan} from './definitions'; import {getDefinitionAndBoundSpan, getTsDefinitionAndBoundSpan} from './definitions';
import {getDeclarationDiagnostics, getTemplateDiagnostics, ngDiagnosticToTsDiagnostic, uniqueBySpan} from './diagnostics'; import {getDeclarationDiagnostics, getTemplateDiagnostics, ngDiagnosticToTsDiagnostic, uniqueBySpan} from './diagnostics';
import {getHover, getTsHover} from './hover'; import {getHover, getTsHover} from './hover';
import {Diagnostic, LanguageService} from './types'; import * as ng from './types';
import {TypeScriptServiceHost} from './typescript_host'; import {TypeScriptServiceHost} from './typescript_host';
/** /**
@ -20,16 +20,16 @@ import {TypeScriptServiceHost} from './typescript_host';
* *
* @publicApi * @publicApi
*/ */
export function createLanguageService(host: TypeScriptServiceHost): LanguageService { export function createLanguageService(host: TypeScriptServiceHost) {
return new LanguageServiceImpl(host); return new LanguageServiceImpl(host);
} }
class LanguageServiceImpl implements LanguageService { class LanguageServiceImpl implements ng.LanguageService {
constructor(private readonly host: TypeScriptServiceHost) {} constructor(private readonly host: TypeScriptServiceHost) {}
getDiagnostics(fileName: string): tss.Diagnostic[] { getSemanticDiagnostics(fileName: string): tss.Diagnostic[] {
const analyzedModules = this.host.getAnalyzedModules(); // same role as 'synchronizeHostData' const analyzedModules = this.host.getAnalyzedModules(); // same role as 'synchronizeHostData'
const results: Diagnostic[] = []; const results: ng.Diagnostic[] = [];
const templates = this.host.getTemplates(fileName); const templates = this.host.getTemplates(fileName);
for (const template of templates) { for (const template of templates) {
@ -48,7 +48,9 @@ class LanguageServiceImpl implements LanguageService {
return uniqueBySpan(results).map(d => ngDiagnosticToTsDiagnostic(d, sourceFile)); return uniqueBySpan(results).map(d => ngDiagnosticToTsDiagnostic(d, sourceFile));
} }
getCompletionsAt(fileName: string, position: number): tss.CompletionInfo|undefined { getCompletionsAtPosition(
fileName: string, position: number,
options?: tss.GetCompletionsAtPositionOptions): tss.CompletionInfo|undefined {
this.host.getAnalyzedModules(); // same role as 'synchronizeHostData' this.host.getAnalyzedModules(); // same role as 'synchronizeHostData'
const ast = this.host.getTemplateAstAtPosition(fileName, position); const ast = this.host.getTemplateAstAtPosition(fileName, position);
if (!ast) { if (!ast) {
@ -67,7 +69,8 @@ class LanguageServiceImpl implements LanguageService {
}; };
} }
getDefinitionAt(fileName: string, position: number): tss.DefinitionInfoAndBoundSpan|undefined { getDefinitionAndBoundSpan(fileName: string, position: number): tss.DefinitionInfoAndBoundSpan
|undefined {
this.host.getAnalyzedModules(); // same role as 'synchronizeHostData' this.host.getAnalyzedModules(); // same role as 'synchronizeHostData'
const templateInfo = this.host.getTemplateAstAtPosition(fileName, position); const templateInfo = this.host.getTemplateAstAtPosition(fileName, position);
if (templateInfo) { if (templateInfo) {
@ -84,7 +87,7 @@ class LanguageServiceImpl implements LanguageService {
} }
} }
getHoverAt(fileName: string, position: number): tss.QuickInfo|undefined { getQuickInfoAtPosition(fileName: string, position: number): tss.QuickInfo|undefined {
this.host.getAnalyzedModules(); // same role as 'synchronizeHostData' this.host.getAnalyzedModules(); // same role as 'synchronizeHostData'
const templateInfo = this.host.getTemplateAstAtPosition(fileName, position); const templateInfo = this.host.getTemplateAstAtPosition(fileName, position);
if (templateInfo) { if (templateInfo) {

View File

@ -36,7 +36,7 @@ export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
return results; return results;
} }
} }
return ngLS.getCompletionsAt(fileName, position); return ngLS.getCompletionsAtPosition(fileName, position, options);
} }
function getQuickInfoAtPosition(fileName: string, position: number): tss.QuickInfo|undefined { function getQuickInfoAtPosition(fileName: string, position: number): tss.QuickInfo|undefined {
@ -47,7 +47,7 @@ export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
return result; return result;
} }
} }
return ngLS.getHoverAt(fileName, position); return ngLS.getQuickInfoAtPosition(fileName, position);
} }
function getSemanticDiagnostics(fileName: string): tss.Diagnostic[] { function getSemanticDiagnostics(fileName: string): tss.Diagnostic[] {
@ -56,7 +56,7 @@ export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
results.push(...tsLS.getSemanticDiagnostics(fileName)); results.push(...tsLS.getSemanticDiagnostics(fileName));
} }
// For semantic diagnostics we need to combine both TS + Angular results // For semantic diagnostics we need to combine both TS + Angular results
results.push(...ngLS.getDiagnostics(fileName)); results.push(...ngLS.getSemanticDiagnostics(fileName));
return results; return results;
} }
@ -69,7 +69,7 @@ export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
return results; return results;
} }
} }
const result = ngLS.getDefinitionAt(fileName, position); const result = ngLS.getDefinitionAndBoundSpan(fileName, position);
if (!result || !result.definitions || !result.definitions.length) { if (!result || !result.definitions || !result.definitions.length) {
return; return;
} }
@ -85,7 +85,7 @@ export function create(info: tss.server.PluginCreateInfo): tss.LanguageService {
return result; return result;
} }
} }
return ngLS.getDefinitionAt(fileName, position); return ngLS.getDefinitionAndBoundSpan(fileName, position);
} }
const proxy: tss.LanguageService = Object.assign( const proxy: tss.LanguageService = Object.assign(

View File

@ -7,7 +7,7 @@
*/ */
import {CompileDirectiveMetadata, NgAnalyzedModules, StaticSymbol} from '@angular/compiler'; import {CompileDirectiveMetadata, NgAnalyzedModules, StaticSymbol} from '@angular/compiler';
import * as ts from 'typescript';
import {AstResult} from './common'; import {AstResult} from './common';
import {BuiltinType, DeclarationKind, Definition, PipeInfo, Pipes, Signature, Span, Symbol, SymbolDeclaration, SymbolQuery, SymbolTable} from './symbols'; import {BuiltinType, DeclarationKind, Definition, PipeInfo, Pipes, Signature, Span, Symbol, SymbolDeclaration, SymbolQuery, SymbolTable} from './symbols';
@ -354,48 +354,12 @@ export interface Hover {
/** /**
* An instance of an Angular language service created by `createLanguageService()`. * An instance of an Angular language service created by `createLanguageService()`.
* *
* The language service returns information about Angular templates that are included in a project * The Angular language service implements a subset of methods defined in
* as defined by the `LanguageServiceHost`. * The Angular language service implements a subset of methods defined by
* * the TypeScript language service.
* When a method expects a `fileName` this file can either be source file in the project that
* contains a template in a string literal or a template file referenced by the project returned
* by `getTemplateReference()`. All other files will cause the method to return `undefined`.
*
* If a method takes a `position`, it is the offset of the UTF-16 code-point relative to the
* beginning of the file reference by `fileName`.
*
* This interface and all interfaces and types marked as `LanguageService` types, describe a
* particular implementation of the Angular language service and is not intended to be
* implemented. Adding members to the interface will not be considered a breaking change as
* defined by SemVer.
*
* Removing a member or making a member optional, changing a method parameters, or changing a
* member's type will all be considered a breaking change.
*
* While an interface is marked as experimental breaking-changes will be allowed between minor
* releases. After an interface is marked as stable breaking-changes will only be allowed between
* major releases. No breaking changes are allowed between patch releases.
* *
* @publicApi * @publicApi
*/ */
export interface LanguageService { export type LanguageService = Pick<
/** ts.LanguageService, 'getCompletionsAtPosition'|'getDefinitionAndBoundSpan'|
* Returns a list of all error for all templates in the given file. 'getQuickInfoAtPosition'|'getSemanticDiagnostics'>;
*/
getDiagnostics(fileName: string): ts.Diagnostic[];
/**
* Return the completions at the given position.
*/
getCompletionsAt(fileName: string, position: number): ts.CompletionInfo|undefined;
/**
* Return the definition location for the symbol at position.
*/
getDefinitionAt(fileName: string, position: number): ts.DefinitionInfoAndBoundSpan|undefined;
/**
* Return the hover information for the symbol at position.
*/
getHoverAt(fileName: string, position: number): ts.QuickInfo|undefined;
}

View File

@ -29,7 +29,7 @@ describe('completions', () => {
it('should be able to get entity completions', () => { it('should be able to get entity completions', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'entity-amp'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'entity-amp');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.ENTITY, ['&amp;', '&gt;', '&lt;', '&iota;']); expectContain(completions, CompletionKind.ENTITY, ['&amp;', '&gt;', '&lt;', '&iota;']);
}); });
@ -37,14 +37,14 @@ describe('completions', () => {
const locations = ['empty', 'start-tag-h1', 'h1-content', 'start-tag', 'start-tag-after-h']; const locations = ['empty', 'start-tag-h1', 'h1-content', 'start-tag', 'start-tag-after-h'];
for (const location of locations) { for (const location of locations) {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, location); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, location);
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.HTML_ELEMENT, ['div', 'h1', 'h2', 'span']); expectContain(completions, CompletionKind.HTML_ELEMENT, ['div', 'h1', 'h2', 'span']);
} }
}); });
it('should be able to return component directives', () => { it('should be able to return component directives', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'empty'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'empty');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.COMPONENT, [ expectContain(completions, CompletionKind.COMPONENT, [
'ng-form', 'ng-form',
'my-app', 'my-app',
@ -55,13 +55,13 @@ describe('completions', () => {
it('should be able to return attribute directives', () => { it('should be able to return attribute directives', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h1-after-space'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h1-after-space');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.ATTRIBUTE, ['string-model', 'number-model']); expectContain(completions, CompletionKind.ATTRIBUTE, ['string-model', 'number-model']);
}); });
it('should be able to return angular pseudo elements', () => { it('should be able to return angular pseudo elements', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'empty'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'empty');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.ANGULAR_ELEMENT, [ expectContain(completions, CompletionKind.ANGULAR_ELEMENT, [
'ng-container', 'ng-container',
'ng-content', 'ng-content',
@ -71,7 +71,7 @@ describe('completions', () => {
it('should be able to return h1 attributes', () => { it('should be able to return h1 attributes', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h1-after-space'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h1-after-space');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.HTML_ATTRIBUTE, [ expectContain(completions, CompletionKind.HTML_ATTRIBUTE, [
'class', 'class',
'id', 'id',
@ -82,7 +82,7 @@ describe('completions', () => {
it('should be able to find common Angular attributes', () => { it('should be able to find common Angular attributes', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'div-attributes'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'div-attributes');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.ATTRIBUTE, [ expectContain(completions, CompletionKind.ATTRIBUTE, [
'ngClass', 'ngClass',
'ngForm', 'ngForm',
@ -94,13 +94,13 @@ describe('completions', () => {
it('should be able to get the completions at the beginning of an interpolation', () => { it('should be able to get the completions at the beginning of an interpolation', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h2-hero'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h2-hero');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['title', 'hero']); expectContain(completions, CompletionKind.PROPERTY, ['title', 'hero']);
}); });
it('should not include private members of a class', () => { it('should not include private members of a class', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h2-hero'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h2-hero');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const internal = completions !.entries.find(e => e.name === 'internal'); const internal = completions !.entries.find(e => e.name === 'internal');
expect(internal).toBeUndefined(); expect(internal).toBeUndefined();
@ -108,20 +108,20 @@ describe('completions', () => {
it('should be able to get the completions at the end of an interpolation', () => { it('should be able to get the completions at the end of an interpolation', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'sub-end'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'sub-end');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['title', 'hero']); expectContain(completions, CompletionKind.PROPERTY, ['title', 'hero']);
}); });
it('should be able to get the completions in a property', () => { it('should be able to get the completions in a property', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h2-name'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h2-name');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
it('should suggest template references', () => { it('should suggest template references', () => {
mockHost.override(TEST_TEMPLATE, `<div *~{cursor}></div>`); mockHost.override(TEST_TEMPLATE, `<div *~{cursor}></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.ATTRIBUTE, [ expectContain(completions, CompletionKind.ATTRIBUTE, [
'ngFor', 'ngFor',
'ngForOf', 'ngForOf',
@ -134,52 +134,52 @@ describe('completions', () => {
it('should be able to return attribute names with an incomplete attribute', () => { it('should be able to return attribute names with an incomplete attribute', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'no-value-attribute'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'no-value-attribute');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.HTML_ATTRIBUTE, ['id', 'class', 'dir', 'lang']); expectContain(completions, CompletionKind.HTML_ATTRIBUTE, ['id', 'class', 'dir', 'lang']);
}); });
it('should be able to return attributes of an incomplete element', () => { it('should be able to return attributes of an incomplete element', () => {
const m1 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-lt'); const m1 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-lt');
const c1 = ngLS.getCompletionsAt(PARSING_CASES, m1.start); const c1 = ngLS.getCompletionsAtPosition(PARSING_CASES, m1.start);
expectContain(c1, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span']); expectContain(c1, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span']);
const m2 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-a'); const m2 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-a');
const c2 = ngLS.getCompletionsAt(PARSING_CASES, m2.start); const c2 = ngLS.getCompletionsAtPosition(PARSING_CASES, m2.start);
expectContain(c2, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span']); expectContain(c2, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span']);
const m3 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-attr'); const m3 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-attr');
const c3 = ngLS.getCompletionsAt(PARSING_CASES, m3.start); const c3 = ngLS.getCompletionsAtPosition(PARSING_CASES, m3.start);
expectContain(c3, CompletionKind.HTML_ATTRIBUTE, ['id', 'class', 'href', 'name']); expectContain(c3, CompletionKind.HTML_ATTRIBUTE, ['id', 'class', 'href', 'name']);
}); });
it('should be able to return completions with a missing closing tag', () => { it('should be able to return completions with a missing closing tag', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'missing-closing'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'missing-closing');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span', 'h1', 'h2']); expectContain(completions, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span', 'h1', 'h2']);
}); });
it('should be able to return common attributes of an unknown tag', () => { it('should be able to return common attributes of an unknown tag', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'unknown-element'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'unknown-element');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.HTML_ATTRIBUTE, ['id', 'dir', 'lang']); expectContain(completions, CompletionKind.HTML_ATTRIBUTE, ['id', 'dir', 'lang']);
}); });
it('should be able to get completions in an empty interpolation', () => { it('should be able to get completions in an empty interpolation', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'empty-interpolation'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'empty-interpolation');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['title', 'subTitle']); expectContain(completions, CompletionKind.PROPERTY, ['title', 'subTitle']);
}); });
it('should suggest $any() type cast function in an interpolation', () => { it('should suggest $any() type cast function in an interpolation', () => {
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'sub-start'); const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'sub-start');
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start); const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start);
expectContain(completions, CompletionKind.METHOD, ['$any']); expectContain(completions, CompletionKind.METHOD, ['$any']);
}); });
it('should suggest attribute values', () => { it('should suggest attribute values', () => {
mockHost.override(TEST_TEMPLATE, `<div [id]="~{cursor}"></div>`); mockHost.override(TEST_TEMPLATE, `<div [id]="~{cursor}"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, [ expectContain(completions, CompletionKind.PROPERTY, [
'title', 'title',
'hero', 'hero',
@ -192,14 +192,14 @@ describe('completions', () => {
it('should suggest event handlers', () => { it('should suggest event handlers', () => {
mockHost.override(TEST_TEMPLATE, `<div (click)="~{cursor}"></div>`); mockHost.override(TEST_TEMPLATE, `<div (click)="~{cursor}"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.METHOD, ['myClick']); expectContain(completions, CompletionKind.METHOD, ['myClick']);
}); });
it('for methods should include parentheses', () => { it('for methods should include parentheses', () => {
mockHost.override(TEST_TEMPLATE, `<div (click)="~{cursor}"></div>`); mockHost.override(TEST_TEMPLATE, `<div (click)="~{cursor}"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expect(completions).toBeDefined(); expect(completions).toBeDefined();
expect(completions !.entries).toContain(jasmine.objectContaining({ expect(completions !.entries).toContain(jasmine.objectContaining({
name: 'myClick', name: 'myClick',
@ -211,7 +211,7 @@ describe('completions', () => {
it('for methods of pipe should not include parentheses', () => { it('for methods of pipe should not include parentheses', () => {
mockHost.override(TEST_TEMPLATE, `<h1>{{title | lowe~{pipe-method} }}`); mockHost.override(TEST_TEMPLATE, `<h1>{{title | lowe~{pipe-method} }}`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'pipe-method'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'pipe-method');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expect(completions).toBeDefined(); expect(completions).toBeDefined();
expect(completions !.entries).toContain(jasmine.objectContaining({ expect(completions !.entries).toContain(jasmine.objectContaining({
name: 'lowercase', name: 'lowercase',
@ -223,7 +223,7 @@ describe('completions', () => {
describe('in external template', () => { describe('in external template', () => {
it('should be able to get entity completions in external template', () => { it('should be able to get entity completions in external template', () => {
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'entity-amp'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'entity-amp');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.ENTITY, ['&amp;', '&gt;', '&lt;', '&iota;']); expectContain(completions, CompletionKind.ENTITY, ['&amp;', '&gt;', '&lt;', '&iota;']);
}); });
@ -231,7 +231,7 @@ describe('completions', () => {
const locations = ['empty', 'start-tag-h1', 'h1-content', 'start-tag', 'start-tag-after-h']; const locations = ['empty', 'start-tag-h1', 'h1-content', 'start-tag', 'start-tag-after-h'];
for (const location of locations) { for (const location of locations) {
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, location); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, location);
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const {entries} = completions !; const {entries} = completions !;
expect(entries).not.toContain(jasmine.objectContaining({name: 'div'})); expect(entries).not.toContain(jasmine.objectContaining({name: 'div'}));
@ -243,7 +243,7 @@ describe('completions', () => {
it('should be able to return element directives', () => { it('should be able to return element directives', () => {
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'empty'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'empty');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.COMPONENT, [ expectContain(completions, CompletionKind.COMPONENT, [
'ng-form', 'ng-form',
'my-app', 'my-app',
@ -254,7 +254,7 @@ describe('completions', () => {
it('should not return html attributes', () => { it('should not return html attributes', () => {
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'h1-after-space'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'h1-after-space');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const {entries} = completions !; const {entries} = completions !;
expect(entries).not.toContain(jasmine.objectContaining({name: 'class'})); expect(entries).not.toContain(jasmine.objectContaining({name: 'class'}));
@ -266,7 +266,7 @@ describe('completions', () => {
it('should be able to find common Angular attributes', () => { it('should be able to find common Angular attributes', () => {
mockHost.override(TEST_TEMPLATE, `<div ~{cursor}></div>`); mockHost.override(TEST_TEMPLATE, `<div ~{cursor}></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.ATTRIBUTE, [ expectContain(completions, CompletionKind.ATTRIBUTE, [
'ngClass', 'ngClass',
'ngForm', 'ngForm',
@ -280,7 +280,7 @@ describe('completions', () => {
describe('with a *ngIf', () => { describe('with a *ngIf', () => {
it('should be able to get completions for exported *ngIf variable', () => { it('should be able to get completions for exported *ngIf variable', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'promised-person-name'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'promised-person-name');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['name', 'age', 'street']); expectContain(completions, CompletionKind.PROPERTY, ['name', 'age', 'street']);
}); });
}); });
@ -289,7 +289,7 @@ describe('completions', () => {
it('should suggest NgForRow members for let initialization expression', () => { it('should suggest NgForRow members for let initialization expression', () => {
mockHost.override(TEST_TEMPLATE, `<div *ngFor="let i=~{cursor}"></div>`); mockHost.override(TEST_TEMPLATE, `<div *ngFor="let i=~{cursor}"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, [ expectContain(completions, CompletionKind.PROPERTY, [
'$implicit', '$implicit',
'ngForOf', 'ngForOf',
@ -305,14 +305,14 @@ describe('completions', () => {
it('should not provide suggestion before the = sign', () => { it('should not provide suggestion before the = sign', () => {
mockHost.override(TEST_TEMPLATE, `<div *ngFor="let i~{cursor}="></div>`); mockHost.override(TEST_TEMPLATE, `<div *ngFor="let i~{cursor}="></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expect(completions).toBeUndefined(); expect(completions).toBeUndefined();
}); });
it('should include field reference', () => { it('should include field reference', () => {
mockHost.override(TEST_TEMPLATE, `<div *ngFor="let x of ~{cursor}"></div>`); mockHost.override(TEST_TEMPLATE, `<div *ngFor="let x of ~{cursor}"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['title', 'heroes', 'league']); expectContain(completions, CompletionKind.PROPERTY, ['title', 'heroes', 'league']);
// the symbol 'x' declared in *ngFor is also in scope. This asserts that // the symbol 'x' declared in *ngFor is also in scope. This asserts that
// we are actually taking the AST into account and not just referring to // we are actually taking the AST into account and not just referring to
@ -323,7 +323,7 @@ describe('completions', () => {
it('should include expression completions', () => { it('should include expression completions', () => {
mockHost.override(TEST_TEMPLATE, `<div *ngFor="let x of hero.~{expr-property-read}"></div>`); mockHost.override(TEST_TEMPLATE, `<div *ngFor="let x of hero.~{expr-property-read}"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'expr-property-read'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'expr-property-read');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['name']); expectContain(completions, CompletionKind.PROPERTY, ['name']);
}); });
@ -334,7 +334,7 @@ describe('completions', () => {
</div> </div>
`); `);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.VARIABLE, ['h']); expectContain(completions, CompletionKind.VARIABLE, ['h']);
}); });
@ -345,13 +345,13 @@ describe('completions', () => {
</div> </div>
`); `);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
it('should be able to infer the type of a ngForOf with an async pipe', () => { it('should be able to infer the type of a ngForOf with an async pipe', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'async-person-name'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'async-person-name');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['name', 'age', 'street']); expectContain(completions, CompletionKind.PROPERTY, ['name', 'age', 'street']);
}); });
@ -364,7 +364,7 @@ describe('completions', () => {
</div> </div>
`); `);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'position'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'position');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
// member variable of type Hero has properties 'id' and 'name'. // member variable of type Hero has properties 'id' and 'name'.
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
@ -374,35 +374,35 @@ describe('completions', () => {
it('should be able to complete property value', () => { it('should be able to complete property value', () => {
mockHost.override(TEST_TEMPLATE, `<h1 [model]="~{cursor}"></h1>`); mockHost.override(TEST_TEMPLATE, `<h1 [model]="~{cursor}"></h1>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['title']); expectContain(completions, CompletionKind.PROPERTY, ['title']);
}); });
it('should be able to complete property read', () => { it('should be able to complete property read', () => {
mockHost.override(TEST_TEMPLATE, `<h1 [model]="hero.~{property-read}"></h1>`); mockHost.override(TEST_TEMPLATE, `<h1 [model]="hero.~{property-read}"></h1>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'property-read'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'property-read');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
it('should be able to complete an event', () => { it('should be able to complete an event', () => {
mockHost.override(TEST_TEMPLATE, `<h1 (model)="~{cursor}"></h1>`); mockHost.override(TEST_TEMPLATE, `<h1 (model)="~{cursor}"></h1>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.METHOD, ['myClick']); expectContain(completions, CompletionKind.METHOD, ['myClick']);
}); });
it('should be able to complete a the LHS of a two-way binding', () => { it('should be able to complete a the LHS of a two-way binding', () => {
mockHost.override(TEST_TEMPLATE, `<div [(~{cursor})]></div>`); mockHost.override(TEST_TEMPLATE, `<div [(~{cursor})]></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.ATTRIBUTE, ['ngModel']); expectContain(completions, CompletionKind.ATTRIBUTE, ['ngModel']);
}); });
it('should be able to complete a the RHS of a two-way binding', () => { it('should be able to complete a the RHS of a two-way binding', () => {
mockHost.override(TEST_TEMPLATE, `<h1 [(model)]="~{cursor}"></h1>`); mockHost.override(TEST_TEMPLATE, `<h1 [(model)]="~{cursor}"></h1>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['title']); expectContain(completions, CompletionKind.PROPERTY, ['title']);
}); });
@ -410,13 +410,13 @@ describe('completions', () => {
// Property binding via [] // Property binding via []
mockHost.override(TEST_TEMPLATE, `<div number-model [~{cursor}]></div>`); mockHost.override(TEST_TEMPLATE, `<div number-model [~{cursor}]></div>`);
const m1 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const m1 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const c1 = ngLS.getCompletionsAt(TEST_TEMPLATE, m1.start); const c1 = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, m1.start);
expectContain(c1, CompletionKind.ATTRIBUTE, ['inputAlias']); expectContain(c1, CompletionKind.ATTRIBUTE, ['inputAlias']);
// Property binding via bind- // Property binding via bind-
mockHost.override(TEST_TEMPLATE, `<div number-model bind-~{cursor}></div>`); mockHost.override(TEST_TEMPLATE, `<div number-model bind-~{cursor}></div>`);
const m2 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const m2 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const c2 = ngLS.getCompletionsAt(TEST_TEMPLATE, m2.start); const c2 = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, m2.start);
expectContain(c2, CompletionKind.ATTRIBUTE, ['inputAlias']); expectContain(c2, CompletionKind.ATTRIBUTE, ['inputAlias']);
}); });
@ -424,13 +424,13 @@ describe('completions', () => {
// Event binding via () // Event binding via ()
mockHost.override(TEST_TEMPLATE, `<div number-model (~{cursor})></div>`); mockHost.override(TEST_TEMPLATE, `<div number-model (~{cursor})></div>`);
const m1 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const m1 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const c1 = ngLS.getCompletionsAt(TEST_TEMPLATE, m1.start); const c1 = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, m1.start);
expectContain(c1, CompletionKind.ATTRIBUTE, ['outputAlias']); expectContain(c1, CompletionKind.ATTRIBUTE, ['outputAlias']);
// Event binding via on- // Event binding via on-
mockHost.override(TEST_TEMPLATE, `<div number-mode on-~{cursor}></div>`); mockHost.override(TEST_TEMPLATE, `<div number-mode on-~{cursor}></div>`);
const m2 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const m2 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const c2 = ngLS.getCompletionsAt(TEST_TEMPLATE, m2.start); const c2 = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, m2.start);
expectContain(c2, CompletionKind.ATTRIBUTE, ['outputAlias']); expectContain(c2, CompletionKind.ATTRIBUTE, ['outputAlias']);
}); });
@ -438,13 +438,13 @@ describe('completions', () => {
// Banana-in-a-box via [()] // Banana-in-a-box via [()]
mockHost.override(TEST_TEMPLATE, `<div string-model [(~{cursor})]></div>`); mockHost.override(TEST_TEMPLATE, `<div string-model [(~{cursor})]></div>`);
const m1 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const m1 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const c1 = ngLS.getCompletionsAt(TEST_TEMPLATE, m1.start); const c1 = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, m1.start);
expectContain(c1, CompletionKind.ATTRIBUTE, ['model']); expectContain(c1, CompletionKind.ATTRIBUTE, ['model']);
// Banana-in-a-box via bindon- // Banana-in-a-box via bindon-
mockHost.override(TEST_TEMPLATE, `<div string-model bindon-~{cursor}></div>`); mockHost.override(TEST_TEMPLATE, `<div string-model bindon-~{cursor}></div>`);
const m2 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const m2 = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const c2 = ngLS.getCompletionsAt(TEST_TEMPLATE, m2.start); const c2 = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, m2.start);
expectContain(c2, CompletionKind.ATTRIBUTE, ['model']); expectContain(c2, CompletionKind.ATTRIBUTE, ['model']);
}); });
}); });
@ -453,7 +453,7 @@ describe('completions', () => {
it('should be able to get a list of pipe values', () => { it('should be able to get a list of pipe values', () => {
for (const location of ['before-pipe', 'in-pipe', 'after-pipe']) { for (const location of ['before-pipe', 'in-pipe', 'after-pipe']) {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, location); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, location);
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.PIPE, [ expectContain(completions, CompletionKind.PIPE, [
'async', 'async',
'uppercase', 'uppercase',
@ -465,7 +465,7 @@ describe('completions', () => {
it('should be able to resolve lowercase', () => { it('should be able to resolve lowercase', () => {
const marker = mockHost.getLocationMarkerFor(EXPRESSION_CASES, 'string-pipe'); const marker = mockHost.getLocationMarkerFor(EXPRESSION_CASES, 'string-pipe');
const completions = ngLS.getCompletionsAt(EXPRESSION_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(EXPRESSION_CASES, marker.start);
expectContain(completions, CompletionKind.METHOD, [ expectContain(completions, CompletionKind.METHOD, [
'charAt', 'charAt',
'replace', 'replace',
@ -478,13 +478,13 @@ describe('completions', () => {
describe('with references', () => { describe('with references', () => {
it('should list references', () => { it('should list references', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'test-comp-content'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'test-comp-content');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.REFERENCE, ['div', 'test1', 'test2']); expectContain(completions, CompletionKind.REFERENCE, ['div', 'test1', 'test2']);
}); });
it('should reference the component', () => { it('should reference the component', () => {
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'test-comp-after-test'); const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'test-comp-after-test');
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['name', 'testEvent']); expectContain(completions, CompletionKind.PROPERTY, ['name', 'testEvent']);
}); });
@ -494,14 +494,14 @@ describe('completions', () => {
<div (click)="test.~{property-read}"></div> <div (click)="test.~{property-read}"></div>
`); `);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'property-read'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'property-read');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['name', 'testEvent']); expectContain(completions, CompletionKind.PROPERTY, ['name', 'testEvent']);
}); });
// TODO: Enable when we have a flag that indicates the project targets the DOM // TODO: Enable when we have a flag that indicates the project targets the DOM
// it('should reference the element if no component', () => { // it('should reference the element if no component', () => {
// const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'test-comp-after-div'); // const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'test-comp-after-div');
// const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start); // const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start);
// expectContain(completions, CompletionKind.PROPERTY, ['innerText']); // expectContain(completions, CompletionKind.PROPERTY, ['innerText']);
// }); // });
}); });
@ -520,7 +520,7 @@ describe('completions', () => {
} }
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'key'); const location = mockHost.getLocationMarkerFor(fileName, 'key');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'key') !; const completion = completions.entries.find(entry => entry.name === 'key') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -537,7 +537,7 @@ describe('completions', () => {
export class FooComponent {} export class FooComponent {}
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'start'); const location = mockHost.getLocationMarkerFor(fileName, 'start');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'acronym') !; const completion = completions.entries.find(entry => entry.name === 'acronym') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -554,7 +554,7 @@ describe('completions', () => {
export class FooComponent {} export class FooComponent {}
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'end'); const location = mockHost.getLocationMarkerFor(fileName, 'end');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'acronym') !; const completion = completions.entries.find(entry => entry.name === 'acronym') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -575,7 +575,7 @@ describe('completions', () => {
} }
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'key'); const location = mockHost.getLocationMarkerFor(fileName, 'key');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'key') !; const completion = completions.entries.find(entry => entry.name === 'key') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -596,7 +596,7 @@ describe('completions', () => {
} }
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'field'); const location = mockHost.getLocationMarkerFor(fileName, 'field');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === '$title_1') !; const completion = completions.entries.find(entry => entry.name === '$title_1') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -615,7 +615,7 @@ describe('completions', () => {
export class FooComponent {} export class FooComponent {}
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'click'); const location = mockHost.getLocationMarkerFor(fileName, 'click');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'click') !; const completion = completions.entries.find(entry => entry.name === 'click') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -636,7 +636,7 @@ describe('completions', () => {
} }
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'handleClick'); const location = mockHost.getLocationMarkerFor(fileName, 'handleClick');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'handleClick') !; const completion = completions.entries.find(entry => entry.name === 'handleClick') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -655,7 +655,7 @@ describe('completions', () => {
export class FooComponent {} export class FooComponent {}
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'div'); const location = mockHost.getLocationMarkerFor(fileName, 'div');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'div') !; const completion = completions.entries.find(entry => entry.name === 'div') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -674,7 +674,7 @@ describe('completions', () => {
export class FooComponent {} export class FooComponent {}
`); `);
const location = mockHost.getLocationMarkerFor(fileName, 'model'); const location = mockHost.getLocationMarkerFor(fileName, 'model');
const completions = ngLS.getCompletionsAt(fileName, location.start) !; const completions = ngLS.getCompletionsAtPosition(fileName, location.start) !;
expect(completions).toBeDefined(); expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === 'ngModel') !; const completion = completions.entries.find(entry => entry.name === 'ngModel') !;
expect(completion).toBeDefined(); expect(completion).toBeDefined();
@ -687,14 +687,14 @@ describe('completions', () => {
it('should work with numeric index signatures (arrays)', () => { it('should work with numeric index signatures (arrays)', () => {
mockHost.override(TEST_TEMPLATE, `{{ heroes[0].~{heroes-number-index}}}`); mockHost.override(TEST_TEMPLATE, `{{ heroes[0].~{heroes-number-index}}}`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'heroes-number-index'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'heroes-number-index');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
it('should work with numeric index signatures (tuple arrays)', () => { it('should work with numeric index signatures (tuple arrays)', () => {
mockHost.override(TEST_TEMPLATE, `{{ tupleArray[1].~{tuple-array-number-index}}}`); mockHost.override(TEST_TEMPLATE, `{{ tupleArray[1].~{tuple-array-number-index}}}`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'tuple-array-number-index'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'tuple-array-number-index');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
@ -702,21 +702,21 @@ describe('completions', () => {
it('should work with index notation', () => { it('should work with index notation', () => {
mockHost.override(TEST_TEMPLATE, `{{ heroesByName['Jacky'].~{heroes-string-index}}}`); mockHost.override(TEST_TEMPLATE, `{{ heroesByName['Jacky'].~{heroes-string-index}}}`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'heroes-string-index'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'heroes-string-index');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
it('should work with dot notation', () => { it('should work with dot notation', () => {
mockHost.override(TEST_TEMPLATE, `{{ heroesByName.jacky.~{heroes-string-index}}}`); mockHost.override(TEST_TEMPLATE, `{{ heroesByName.jacky.~{heroes-string-index}}}`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'heroes-string-index'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'heroes-string-index');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']); expectContain(completions, CompletionKind.PROPERTY, ['id', 'name']);
}); });
it('should work with dot notation if stringIndexType is a primitive type', () => { it('should work with dot notation if stringIndexType is a primitive type', () => {
mockHost.override(TEST_TEMPLATE, `{{ primitiveIndexType.test.~{string-primitive-type}}}`); mockHost.override(TEST_TEMPLATE, `{{ primitiveIndexType.test.~{string-primitive-type}}}`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'string-primitive-type'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'string-primitive-type');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.METHOD, ['substring']); expectContain(completions, CompletionKind.METHOD, ['substring']);
}); });
}); });
@ -725,14 +725,14 @@ describe('completions', () => {
it('should be able to get the completions (ref- prefix)', () => { it('should be able to get the completions (ref- prefix)', () => {
mockHost.override(TEST_TEMPLATE, `<form ref-itemForm="ngF~{reference}"></form>`); mockHost.override(TEST_TEMPLATE, `<form ref-itemForm="ngF~{reference}"></form>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'reference'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'reference');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start) !; const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start) !;
expectContain(completions, CompletionKind.REFERENCE, ['ngForm']); expectContain(completions, CompletionKind.REFERENCE, ['ngForm']);
}); });
it('should be able to get the completions (# prefix)', () => { it('should be able to get the completions (# prefix)', () => {
mockHost.override(TEST_TEMPLATE, `<form #itemForm="ngF~{reference}"></form>`); mockHost.override(TEST_TEMPLATE, `<form #itemForm="ngF~{reference}"></form>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'reference'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'reference');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start) !; const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start) !;
expectContain(completions, CompletionKind.REFERENCE, ['ngForm']); expectContain(completions, CompletionKind.REFERENCE, ['ngForm']);
}); });
}); });
@ -741,7 +741,7 @@ describe('completions', () => {
it('should not expand i18n templates', () => { it('should not expand i18n templates', () => {
mockHost.override(TEST_TEMPLATE, `<div i18n="@@el">{{~{cursor}}}</div>`); mockHost.override(TEST_TEMPLATE, `<div i18n="@@el">{{~{cursor}}}</div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.PROPERTY, ['title']); expectContain(completions, CompletionKind.PROPERTY, ['title']);
}); });
@ -749,7 +749,7 @@ describe('completions', () => {
it('should suggest $event in event bindings', () => { it('should suggest $event in event bindings', () => {
mockHost.override(TEST_TEMPLATE, `<div (click)="myClick(~{cursor});"></div>`); mockHost.override(TEST_TEMPLATE, `<div (click)="myClick(~{cursor});"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start); const completions = ngLS.getCompletionsAtPosition(TEST_TEMPLATE, marker.start);
expectContain(completions, CompletionKind.VARIABLE, ['$event']); expectContain(completions, CompletionKind.VARIABLE, ['$event']);
}); });
}); });

View File

@ -33,7 +33,7 @@ describe('definitions', () => {
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'name'); const marker = mockHost.getReferenceMarkerFor(fileName, 'name');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -58,7 +58,7 @@ describe('definitions', () => {
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'name'); const marker = mockHost.getReferenceMarkerFor(fileName, 'name');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -83,7 +83,7 @@ describe('definitions', () => {
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'myClick'); const marker = mockHost.getReferenceMarkerFor(fileName, 'myClick');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -108,7 +108,7 @@ describe('definitions', () => {
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'include'); const marker = mockHost.getReferenceMarkerFor(fileName, 'include');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -133,7 +133,7 @@ describe('definitions', () => {
// Get the marker for «test-comp» in the code added above. // Get the marker for «test-comp» in the code added above.
const marker = mockHost.getReferenceMarkerFor(fileName, 'test-comp'); const marker = mockHost.getReferenceMarkerFor(fileName, 'test-comp');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -170,7 +170,7 @@ describe('definitions', () => {
// Get the marker for «test» in the code added above. // Get the marker for «test» in the code added above.
const marker = mockHost.getReferenceMarkerFor(fileName, 'test'); const marker = mockHost.getReferenceMarkerFor(fileName, 'test');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -207,7 +207,7 @@ describe('definitions', () => {
// Get the marker for «test» in the code added above. // Get the marker for «test» in the code added above.
const marker = mockHost.getReferenceMarkerFor(fileName, 'tcName'); const marker = mockHost.getReferenceMarkerFor(fileName, 'tcName');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -244,7 +244,7 @@ describe('definitions', () => {
// Get the marker for «test» in the code added above. // Get the marker for «test» in the code added above.
const marker = mockHost.getReferenceMarkerFor(fileName, 'async'); const marker = mockHost.getReferenceMarkerFor(fileName, 'async');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -270,7 +270,7 @@ describe('definitions', () => {
// Get the marker for ngIf in the code added above. // Get the marker for ngIf in the code added above.
const marker = mockHost.getReferenceMarkerFor(TEST_TEMPLATE, 'ngIf'); const marker = mockHost.getReferenceMarkerFor(TEST_TEMPLATE, 'ngIf');
const result = ngService.getDefinitionAt(TEST_TEMPLATE, marker.start); const result = ngService.getDefinitionAndBoundSpan(TEST_TEMPLATE, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -296,7 +296,7 @@ describe('definitions', () => {
// Get the marker for «model» in the code added above. // Get the marker for «model» in the code added above.
const marker = mockHost.getReferenceMarkerFor(TEST_TEMPLATE, 'model'); const marker = mockHost.getReferenceMarkerFor(TEST_TEMPLATE, 'model');
const result = ngService.getDefinitionAt(TEST_TEMPLATE, marker.start); const result = ngService.getDefinitionAndBoundSpan(TEST_TEMPLATE, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -326,7 +326,7 @@ describe('definitions', () => {
export class MyComponent {}`); export class MyComponent {}`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'test'); const marker = mockHost.getReferenceMarkerFor(fileName, 'test');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -349,7 +349,7 @@ describe('definitions', () => {
export class MyComponent {}`); export class MyComponent {}`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'test'); const marker = mockHost.getReferenceMarkerFor(fileName, 'test');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;
@ -373,7 +373,7 @@ describe('definitions', () => {
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'name'); const marker = mockHost.getReferenceMarkerFor(fileName, 'name');
const result = ngService.getDefinitionAt(fileName, marker.start); const result = ngService.getDefinitionAndBoundSpan(fileName, marker.start);
expect(result).toBeDefined(); expect(result).toBeDefined();
const {textSpan, definitions} = result !; const {textSpan, definitions} = result !;

View File

@ -39,7 +39,7 @@ describe('diagnostics', () => {
it('should produce no diagnostics for test.ng', () => { it('should produce no diagnostics for test.ng', () => {
// there should not be any errors on existing external template // there should not be any errors on existing external template
expect(ngLS.getDiagnostics('/app/test.ng')).toEqual([]); expect(ngLS.getSemanticDiagnostics('/app/test.ng')).toEqual([]);
}); });
it('should not return TS and NG errors for existing files', () => { it('should not return TS and NG errors for existing files', () => {
@ -52,14 +52,14 @@ describe('diagnostics', () => {
expect(syntaxDiags).toEqual([]); expect(syntaxDiags).toEqual([]);
const semanticDiags = tsLS.getSemanticDiagnostics(file); const semanticDiags = tsLS.getSemanticDiagnostics(file);
expect(semanticDiags).toEqual([]); expect(semanticDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(file); const ngDiags = ngLS.getSemanticDiagnostics(file);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
} }
}); });
it('should report error for unexpected end of expression', () => { it('should report error for unexpected end of expression', () => {
const content = mockHost.override(TEST_TEMPLATE, `{{ 5 / }}`); const content = mockHost.override(TEST_TEMPLATE, `{{ 5 / }}`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
const {messageText, start, length} = diags[0]; const {messageText, start, length} = diags[0];
expect(messageText) expect(messageText)
@ -73,7 +73,7 @@ describe('diagnostics', () => {
// https://github.com/angular/vscode-ng-language-service/issues/242 // https://github.com/angular/vscode-ng-language-service/issues/242
it('should support $any() type cast function', () => { it('should support $any() type cast function', () => {
mockHost.override(TEST_TEMPLATE, `<div>{{$any(title).xyz}}</div>`); mockHost.override(TEST_TEMPLATE, `<div>{{$any(title).xyz}}</div>`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags).toEqual([]); expect(diags).toEqual([]);
}); });
@ -84,7 +84,7 @@ describe('diagnostics', () => {
]; ];
for (const template of templates) { for (const template of templates) {
mockHost.override(TEST_TEMPLATE, template); mockHost.override(TEST_TEMPLATE, template);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
expect(diags[0].messageText).toBe('Unable to resolve signature for call of method $any'); expect(diags[0].messageText).toBe('Unable to resolve signature for call of method $any');
} }
@ -95,7 +95,7 @@ describe('diagnostics', () => {
<div *ngFor="let h of heroes | slice:0:1"> <div *ngFor="let h of heroes | slice:0:1">
{{h.name}} {{h.name}}
</div>`); </div>`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags).toEqual([]); expect(diags).toEqual([]);
}); });
@ -104,7 +104,7 @@ describe('diagnostics', () => {
<div *ngFor="let h of heroes | slice:0:1"> <div *ngFor="let h of heroes | slice:0:1">
{{h.age}} {{h.age}}
</div>`); </div>`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
expect(diags[0].messageText) expect(diags[0].messageText)
.toBe(`Identifier 'age' is not defined. 'Hero' does not contain such a member`); .toBe(`Identifier 'age' is not defined. 'Hero' does not contain such a member`);
@ -116,7 +116,7 @@ describe('diagnostics', () => {
<span (click)="greet()"></span> <span (click)="greet()"></span>
</ng-template> </ng-template>
`); `);
const diagnostics = ngLS.getDiagnostics(TEST_TEMPLATE); const diagnostics = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diagnostics).toEqual([]); expect(diagnostics).toEqual([]);
}); });
@ -128,7 +128,7 @@ describe('diagnostics', () => {
{{ i === isFirst }} {{ i === isFirst }}
</div> </div>
`); `);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
expect(diags[0].messageText).toBe(`Expected the operants to be of similar type or any`); expect(diags[0].messageText).toBe(`Expected the operants to be of similar type or any`);
}); });
@ -140,7 +140,7 @@ describe('diagnostics', () => {
{{ i < 2 }} {{ i < 2 }}
</div> </div>
`); `);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(0); expect(diags.length).toBe(0);
}); });
}); });
@ -149,7 +149,7 @@ describe('diagnostics', () => {
it('should work with numeric index signatures (arrays)', () => { it('should work with numeric index signatures (arrays)', () => {
mockHost.override(TEST_TEMPLATE, ` mockHost.override(TEST_TEMPLATE, `
{{heroes[0].badProperty}}`); {{heroes[0].badProperty}}`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
expect(diags[0].messageText) expect(diags[0].messageText)
.toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`); .toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`);
@ -159,7 +159,7 @@ describe('diagnostics', () => {
it('should work with index notation', () => { it('should work with index notation', () => {
mockHost.override(TEST_TEMPLATE, ` mockHost.override(TEST_TEMPLATE, `
{{heroesByName['Jacky'].badProperty}}`); {{heroesByName['Jacky'].badProperty}}`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
expect(diags[0].messageText) expect(diags[0].messageText)
.toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`); .toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`);
@ -168,7 +168,7 @@ describe('diagnostics', () => {
it('should work with dot notation', () => { it('should work with dot notation', () => {
mockHost.override(TEST_TEMPLATE, ` mockHost.override(TEST_TEMPLATE, `
{{heroesByName.jacky.badProperty}}`); {{heroesByName.jacky.badProperty}}`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
expect(diags[0].messageText) expect(diags[0].messageText)
.toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`); .toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`);
@ -177,7 +177,7 @@ describe('diagnostics', () => {
it('should not produce errors with dot notation if stringIndexType is a primitive type', it('should not produce errors with dot notation if stringIndexType is a primitive type',
() => { () => {
mockHost.override(TEST_TEMPLATE, `{{primitiveIndexType.test}}`); mockHost.override(TEST_TEMPLATE, `{{primitiveIndexType.test}}`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(0); expect(diags.length).toBe(0);
}); });
}); });
@ -186,7 +186,7 @@ describe('diagnostics', () => {
it('should produce diagnostics for invalid tuple type property access', () => { it('should produce diagnostics for invalid tuple type property access', () => {
mockHost.override(TEST_TEMPLATE, ` mockHost.override(TEST_TEMPLATE, `
{{tupleArray[1].badProperty}}`); {{tupleArray[1].badProperty}}`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
expect(diags[0].messageText) expect(diags[0].messageText)
.toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`); .toBe(`Identifier 'badProperty' is not defined. 'Hero' does not contain such a member`);
@ -195,7 +195,7 @@ describe('diagnostics', () => {
it('should not produce errors if tuple array index out of bound', () => { it('should not produce errors if tuple array index out of bound', () => {
mockHost.override(TEST_TEMPLATE, ` mockHost.override(TEST_TEMPLATE, `
{{tupleArray[2].badProperty}}`); {{tupleArray[2].badProperty}}`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags).toEqual([]); expect(diags).toEqual([]);
}); });
@ -203,13 +203,13 @@ describe('diagnostics', () => {
mockHost.override(TEST_TEMPLATE, ` mockHost.override(TEST_TEMPLATE, `
<test-comp (test)="myClick.bind(this)"> <test-comp (test)="myClick.bind(this)">
</test-comp>`); </test-comp>`);
const diags = ngLS.getDiagnostics(TEST_TEMPLATE); const diags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diags).toEqual([]); expect(diags).toEqual([]);
}); });
describe('in expression-cases.ts', () => { describe('in expression-cases.ts', () => {
it('should report access to an unknown field', () => { it('should report access to an unknown field', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain( expect(diags).toContain(
`Identifier 'foo' is not defined. ` + `Identifier 'foo' is not defined. ` +
`The component declaration, template variable declarations, ` + `The component declaration, template variable declarations, ` +
@ -217,25 +217,25 @@ describe('diagnostics', () => {
}); });
it('should report access to an unknown sub-field', () => { it('should report access to an unknown sub-field', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain( expect(diags).toContain(
`Identifier 'nam' is not defined. 'Person' does not contain such a member`); `Identifier 'nam' is not defined. 'Person' does not contain such a member`);
}); });
it('should report access to a private member', () => { it('should report access to a private member', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain(`Identifier 'myField' refers to a private member of the component`); expect(diags).toContain(`Identifier 'myField' refers to a private member of the component`);
}); });
it('should report numeric operator errors', () => { it('should report numeric operator errors', () => {
const diags = ngLS.getDiagnostics(EXPRESSION_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(EXPRESSION_CASES).map(d => d.messageText);
expect(diags).toContain('Expected a numeric type'); expect(diags).toContain('Expected a numeric type');
}); });
}); });
describe('in ng-for-cases.ts', () => { describe('in ng-for-cases.ts', () => {
it('should report an unknown field', () => { it('should report an unknown field', () => {
const diags = ngLS.getDiagnostics(NG_FOR_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(NG_FOR_CASES).map(d => d.messageText);
expect(diags).toContain( expect(diags).toContain(
`Identifier 'people_1' is not defined. ` + `Identifier 'people_1' is not defined. ` +
`The component declaration, template variable declarations, ` + `The component declaration, template variable declarations, ` +
@ -243,12 +243,12 @@ describe('diagnostics', () => {
}); });
it('should report an unknown context reference', () => { it('should report an unknown context reference', () => {
const diags = ngLS.getDiagnostics(NG_FOR_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(NG_FOR_CASES).map(d => d.messageText);
expect(diags).toContain(`The template context does not define a member called 'even_1'`); expect(diags).toContain(`The template context does not define a member called 'even_1'`);
}); });
it('should report an unknown value in a key expression', () => { it('should report an unknown value in a key expression', () => {
const diags = ngLS.getDiagnostics(NG_FOR_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(NG_FOR_CASES).map(d => d.messageText);
expect(diags).toContain( expect(diags).toContain(
`Identifier 'trackBy_1' is not defined. ` + `Identifier 'trackBy_1' is not defined. ` +
`The component declaration, template variable declarations, ` + `The component declaration, template variable declarations, ` +
@ -258,7 +258,7 @@ describe('diagnostics', () => {
describe('in ng-if-cases.ts', () => { describe('in ng-if-cases.ts', () => {
it('should report an implicit context reference', () => { it('should report an implicit context reference', () => {
const diags = ngLS.getDiagnostics(NG_IF_CASES).map(d => d.messageText); const diags = ngLS.getSemanticDiagnostics(NG_IF_CASES).map(d => d.messageText);
expect(diags).toContain(`The template context does not define a member called 'unknown'`); expect(diags).toContain(`The template context does not define a member called 'unknown'`);
}); });
}); });
@ -267,7 +267,7 @@ describe('diagnostics', () => {
it('should not report diagnostic on iteration of any', () => { it('should not report diagnostic on iteration of any', () => {
const fileName = '/app/test.ng'; const fileName = '/app/test.ng';
mockHost.override(fileName, '<div *ngFor="let value of anyValue">{{value.someField}}</div>'); mockHost.override(fileName, '<div *ngFor="let value of anyValue">{{value.someField}}</div>');
const diagnostics = ngLS.getDiagnostics(fileName); const diagnostics = ngLS.getSemanticDiagnostics(fileName);
expect(diagnostics).toEqual([]); expect(diagnostics).toEqual([]);
}); });
@ -279,7 +279,7 @@ describe('diagnostics', () => {
</div> </div>
</div> </div>
`); `);
const diagnostics = ngLS.getDiagnostics(TEST_TEMPLATE); const diagnostics = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(diagnostics.length).toBe(1); expect(diagnostics.length).toBe(1);
const {messageText, start, length} = diagnostics[0]; const {messageText, start, length} = diagnostics[0];
expect(messageText) expect(messageText)
@ -292,14 +292,14 @@ describe('diagnostics', () => {
it('should accept an event', () => { it('should accept an event', () => {
const fileName = '/app/test.ng'; const fileName = '/app/test.ng';
mockHost.override(fileName, '<div (click)="myClick($event)">Click me!</div>'); mockHost.override(fileName, '<div (click)="myClick($event)">Click me!</div>');
const diagnostics = ngLS.getDiagnostics(fileName); const diagnostics = ngLS.getSemanticDiagnostics(fileName);
expect(diagnostics).toEqual([]); expect(diagnostics).toEqual([]);
}); });
it('should reject it when not in an event binding', () => { it('should reject it when not in an event binding', () => {
const fileName = '/app/test.ng'; const fileName = '/app/test.ng';
const content = mockHost.override(fileName, '<div [tabIndex]="$event"></div>'); const content = mockHost.override(fileName, '<div [tabIndex]="$event"></div>');
const diagnostics = ngLS.getDiagnostics(fileName) !; const diagnostics = ngLS.getSemanticDiagnostics(fileName) !;
expect(diagnostics.length).toBe(1); expect(diagnostics.length).toBe(1);
const {messageText, start, length} = diagnostics[0]; const {messageText, start, length} = diagnostics[0];
expect(messageText) expect(messageText)
@ -317,7 +317,7 @@ describe('diagnostics', () => {
template: '<div *ngFor></div> ~{after-div}' template: '<div *ngFor></div> ~{after-div}'
}) })
export class MyComponent {}`); export class MyComponent {}`);
expect(() => ngLS.getDiagnostics(fileName)).not.toThrow(); expect(() => ngLS.getSemanticDiagnostics(fileName)).not.toThrow();
}); });
it('should report a component not in a module', () => { it('should report a component not in a module', () => {
@ -326,7 +326,7 @@ describe('diagnostics', () => {
template: '<div></div>' template: '<div></div>'
}) })
export class MyComponent {}`); export class MyComponent {}`);
const diagnostics = ngLS.getDiagnostics(fileName) !; const diagnostics = ngLS.getSemanticDiagnostics(fileName) !;
expect(diagnostics.length).toBe(1); expect(diagnostics.length).toBe(1);
const {messageText, start, length} = diagnostics[0]; const {messageText, start, length} = diagnostics[0];
expect(messageText) expect(messageText)
@ -348,7 +348,7 @@ describe('diagnostics', () => {
export class AppComponent {}`); export class AppComponent {}`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -358,7 +358,7 @@ describe('diagnostics', () => {
template: '<a *ngIf="(auth.isAdmin | async) || (event.leads && event.leads[(auth.uid | async)])"></a>' template: '<a *ngIf="(auth.isAdmin | async) || (event.leads && event.leads[(auth.uid | async)])"></a>'
}) })
export class MyComponent {}`); export class MyComponent {}`);
expect(() => ngLS.getDiagnostics(fileName)).not.toThrow(); expect(() => ngLS.getSemanticDiagnostics(fileName)).not.toThrow();
}); });
it('should not throw using a directive with no value', () => { it('should not throw using a directive with no value', () => {
@ -369,7 +369,7 @@ describe('diagnostics', () => {
export class MyComponent { export class MyComponent {
name = 'some name'; name = 'some name';
}`); }`);
expect(() => ngLS.getDiagnostics(fileName)).not.toThrow(); expect(() => ngLS.getSemanticDiagnostics(fileName)).not.toThrow();
}); });
it('should report an error for invalid metadata', () => { it('should report an error for invalid metadata', () => {
@ -387,7 +387,7 @@ describe('diagnostics', () => {
}`); }`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT) !; const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT) !;
expect(ngDiags.length).toBe(1); expect(ngDiags.length).toBe(1);
const {messageText, start, length} = ngDiags[0]; const {messageText, start, length} = ngDiags[0];
const keyword = `() => 'foo'`; const keyword = `() => 'foo'`;
@ -409,7 +409,7 @@ describe('diagnostics', () => {
@Component({ @Component({
template: '' template: ''
}) class`); }) class`);
expect(() => ngLS.getDiagnostics(fileName)).not.toThrow(); expect(() => ngLS.getSemanticDiagnostics(fileName)).not.toThrow();
}); });
it('should not report an error for sub-types of string in non-strict mode', () => { it('should not report an error for sub-types of string in non-strict mode', () => {
@ -427,7 +427,7 @@ describe('diagnostics', () => {
}); });
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -446,7 +446,7 @@ describe('diagnostics', () => {
}); });
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -460,7 +460,7 @@ describe('diagnostics', () => {
export class AppComponent { export class AppComponent {
onClick() { } onClick() { }
}`); }`);
const diagnostics = ngLS.getDiagnostics(APP_COMPONENT) !; const diagnostics = ngLS.getSemanticDiagnostics(APP_COMPONENT) !;
const {messageText, start, length} = diagnostics[0]; const {messageText, start, length} = diagnostics[0];
expect(messageText).toBe('Unexpected callable expression. Expected a method call'); expect(messageText).toBe('Unexpected callable expression. Expected a method call');
const keyword = `"onClick"`; const keyword = `"onClick"`;
@ -484,7 +484,7 @@ describe('diagnostics', () => {
}); });
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -501,7 +501,7 @@ describe('diagnostics', () => {
}`); }`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags.length).toBe(1); expect(ngDiags.length).toBe(1);
const {messageText, start, length} = ngDiags[0]; const {messageText, start, length} = ngDiags[0];
expect(messageText).toBe(`The pipe 'dat' could not be found`); expect(messageText).toBe(`The pipe 'dat' could not be found`);
@ -521,7 +521,7 @@ describe('diagnostics', () => {
export class AppComponent {}`); export class AppComponent {}`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -550,7 +550,7 @@ describe('diagnostics', () => {
}`); }`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -568,7 +568,7 @@ describe('diagnostics', () => {
const msgText = ts.flattenDiagnosticMessageText(tsDiags[0].messageText, '\n'); const msgText = ts.flattenDiagnosticMessageText(tsDiags[0].messageText, '\n');
expect(msgText).toBe( expect(msgText).toBe(
`Type 'null[]' is not assignable to type 'Provider[]'.\n Type 'null' is not assignable to type 'Provider'.`); `Type 'null[]' is not assignable to type 'Provider[]'.\n Type 'null' is not assignable to type 'Provider'.`);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags.length).toBe(1); expect(ngDiags.length).toBe(1);
const {messageText, start, length} = ngDiags[0]; const {messageText, start, length} = ngDiags[0];
expect(messageText) expect(messageText)
@ -596,7 +596,7 @@ describe('diagnostics', () => {
export class AppComponent {}`); export class AppComponent {}`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -618,7 +618,7 @@ describe('diagnostics', () => {
}`); }`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -642,7 +642,7 @@ describe('diagnostics', () => {
}`); }`);
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(APP_COMPONENT); const ngDiags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
@ -666,7 +666,7 @@ describe('diagnostics', () => {
}); });
const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT); const tsDiags = tsLS.getSemanticDiagnostics(APP_COMPONENT);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const diagnostic = ngLS.getDiagnostics(APP_COMPONENT); const diagnostic = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(diagnostic).toEqual([]); expect(diagnostic).toEqual([]);
}); });
@ -702,7 +702,7 @@ describe('diagnostics', () => {
const marker = mockHost.getReferenceMarkerFor(fileName, 'notAFile'); const marker = mockHost.getReferenceMarkerFor(fileName, 'notAFile');
const diagnostics = ngLS.getDiagnostics(fileName) !; const diagnostics = ngLS.getSemanticDiagnostics(fileName) !;
const urlDiagnostic = const urlDiagnostic =
diagnostics.find(d => d.messageText === 'URL does not point to a valid file'); diagnostics.find(d => d.messageText === 'URL does not point to a valid file');
expect(urlDiagnostic).toBeDefined(); expect(urlDiagnostic).toBeDefined();
@ -719,7 +719,7 @@ describe('diagnostics', () => {
}) })
export class MyComponent {}`); export class MyComponent {}`);
const diagnostics = ngLS.getDiagnostics(fileName) !; const diagnostics = ngLS.getSemanticDiagnostics(fileName) !;
const urlDiagnostic = const urlDiagnostic =
diagnostics.find(d => d.messageText === 'URL does not point to a valid file'); diagnostics.find(d => d.messageText === 'URL does not point to a valid file');
expect(urlDiagnostic).toBeUndefined(); expect(urlDiagnostic).toBeUndefined();
@ -733,7 +733,7 @@ describe('diagnostics', () => {
selector: 'app-example', selector: 'app-example',
}) })
export class AppComponent {}`); export class AppComponent {}`);
const diags = ngLS.getDiagnostics(APP_COMPONENT); const diags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
const {file, messageText, start, length} = diags[0]; const {file, messageText, start, length} = diags[0];
expect(file !.fileName).toBe(APP_COMPONENT); expect(file !.fileName).toBe(APP_COMPONENT);
@ -752,7 +752,7 @@ describe('diagnostics', () => {
templateUrl: './test.ng', templateUrl: './test.ng',
}) })
export class AppComponent {}`); export class AppComponent {}`);
const diags = ngLS.getDiagnostics(APP_COMPONENT); const diags = ngLS.getSemanticDiagnostics(APP_COMPONENT);
expect(diags.length).toBe(1); expect(diags.length).toBe(1);
const {file, messageText, start, length} = diags[0]; const {file, messageText, start, length} = diags[0];
expect(file !.fileName).toBe(APP_COMPONENT); expect(file !.fileName).toBe(APP_COMPONENT);
@ -771,7 +771,7 @@ describe('diagnostics', () => {
const marker = mockHost.getReferenceMarkerFor(fileName, 'notAFile'); const marker = mockHost.getReferenceMarkerFor(fileName, 'notAFile');
const diagnostics = ngLS.getDiagnostics(fileName) !; const diagnostics = ngLS.getSemanticDiagnostics(fileName) !;
const urlDiagnostic = const urlDiagnostic =
diagnostics.find(d => d.messageText === 'URL does not point to a valid file'); diagnostics.find(d => d.messageText === 'URL does not point to a valid file');
expect(urlDiagnostic).toBeDefined(); expect(urlDiagnostic).toBeDefined();
@ -791,7 +791,7 @@ describe('diagnostics', () => {
}) })
export class AppComponent {}`); export class AppComponent {}`);
const diagnostics = ngLS.getDiagnostics(APP_COMPONENT) !; const diagnostics = ngLS.getSemanticDiagnostics(APP_COMPONENT) !;
expect(diagnostics.length).toBe(0); expect(diagnostics.length).toBe(0);
}); });
}); });
@ -804,7 +804,7 @@ describe('diagnostics', () => {
// Source span information is lost in the process. // Source span information is lost in the process.
const content = mockHost.override( const content = mockHost.override(
TEST_TEMPLATE, '\r\n<div>\r\n{{line0}}\r\n{{line1}}\r\n{{line2}}\r\n</div>'); TEST_TEMPLATE, '\r\n<div>\r\n{{line0}}\r\n{{line1}}\r\n{{line2}}\r\n</div>');
const ngDiags = ngLS.getDiagnostics(TEST_TEMPLATE); const ngDiags = ngLS.getSemanticDiagnostics(TEST_TEMPLATE);
expect(ngDiags.length).toBe(3); expect(ngDiags.length).toBe(3);
for (let i = 0; i < 3; ++i) { for (let i = 0; i < 3; ++i) {
const {messageText, start, length} = ngDiags[i]; const {messageText, start, length} = ngDiags[i];
@ -823,7 +823,7 @@ describe('diagnostics', () => {
const fileName = mockHost.addCode( const fileName = mockHost.addCode(
'\n@Component({template:`\r\n\r\n{{line}}`})export class ComponentCRLF {}'); '\n@Component({template:`\r\n\r\n{{line}}`})export class ComponentCRLF {}');
const content = mockHost.readFile(fileName) !; const content = mockHost.readFile(fileName) !;
const ngDiags = ngLS.getDiagnostics(fileName); const ngDiags = ngLS.getSemanticDiagnostics(fileName);
expect(ngDiags.length).toBeGreaterThan(0); expect(ngDiags.length).toBeGreaterThan(0);
const {messageText, start, length} = ngDiags[0]; const {messageText, start, length} = ngDiags[0];
expect(messageText) expect(messageText)
@ -846,7 +846,7 @@ describe('diagnostics', () => {
`); `);
const tsDiags = tsLS.getSemanticDiagnostics(fileName); const tsDiags = tsLS.getSemanticDiagnostics(fileName);
expect(tsDiags).toEqual([]); expect(tsDiags).toEqual([]);
const ngDiags = ngLS.getDiagnostics(fileName); const ngDiags = ngLS.getSemanticDiagnostics(fileName);
expect(ngDiags).toEqual([]); expect(ngDiags).toEqual([]);
}); });
}); });

View File

@ -32,7 +32,7 @@ describe('hover', () => {
name: string; name: string;
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'name'); const marker = mockHost.getReferenceMarkerFor(fileName, 'name');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -48,7 +48,7 @@ describe('hover', () => {
name: string; name: string;
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'name'); const marker = mockHost.getReferenceMarkerFor(fileName, 'name');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -64,7 +64,7 @@ describe('hover', () => {
myClick() { } myClick() { }
}`); }`);
const marker = mockHost.getDefinitionMarkerFor(fileName, 'myClick'); const marker = mockHost.getDefinitionMarkerFor(fileName, 'myClick');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -81,7 +81,7 @@ describe('hover', () => {
include = true; include = true;
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'include'); const marker = mockHost.getReferenceMarkerFor(fileName, 'include');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -95,7 +95,7 @@ describe('hover', () => {
}) })
export class MyComponent { }`); export class MyComponent { }`);
const marker = mockHost.getDefinitionMarkerFor(fileName, 'test'); const marker = mockHost.getDefinitionMarkerFor(fileName, 'test');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -109,7 +109,7 @@ describe('hover', () => {
}) })
export class MyComponent { }`); export class MyComponent { }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'string-model'); const marker = mockHost.getReferenceMarkerFor(fileName, 'string-model');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -125,7 +125,7 @@ describe('hover', () => {
myHandler() {} myHandler() {}
}`); }`);
const marker = mockHost.getDefinitionMarkerFor(fileName, 'test'); const marker = mockHost.getDefinitionMarkerFor(fileName, 'test');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -141,7 +141,7 @@ describe('hover', () => {
name = 'my name'; name = 'my name';
}`); }`);
const marker = mockHost.getDefinitionMarkerFor(fileName, 'tcName'); const marker = mockHost.getDefinitionMarkerFor(fileName, 'tcName');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -151,7 +151,7 @@ describe('hover', () => {
it('should be able to find a structural directive', () => { it('should be able to find a structural directive', () => {
mockHost.override(TEST_TEMPLATE, `<div «*ᐱngIfᐱ="true"»></div>`); mockHost.override(TEST_TEMPLATE, `<div «*ᐱngIfᐱ="true"»></div>`);
const marker = mockHost.getDefinitionMarkerFor(TEST_TEMPLATE, 'ngIf'); const marker = mockHost.getDefinitionMarkerFor(TEST_TEMPLATE, 'ngIf');
const quickInfo = ngLS.getHoverAt(TEST_TEMPLATE, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -161,7 +161,7 @@ describe('hover', () => {
it('should be able to find a reference to a two-way binding', () => { it('should be able to find a reference to a two-way binding', () => {
mockHost.override(TEST_TEMPLATE, `<test-comp string-model «[(ᐱmodelᐱ)]="title"»></test-comp>`); mockHost.override(TEST_TEMPLATE, `<test-comp string-model «[(ᐱmodelᐱ)]="title"»></test-comp>`);
const marker = mockHost.getDefinitionMarkerFor(TEST_TEMPLATE, 'model'); const marker = mockHost.getDefinitionMarkerFor(TEST_TEMPLATE, 'model');
const quickInfo = ngLS.getHoverAt(TEST_TEMPLATE, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -175,7 +175,7 @@ describe('hover', () => {
}) })
export class MyComponent { }`); export class MyComponent { }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'chart'); const marker = mockHost.getReferenceMarkerFor(fileName, 'chart');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeUndefined(); expect(quickInfo).toBeUndefined();
}); });
@ -191,7 +191,7 @@ describe('hover', () => {
name: string; name: string;
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'AppComponent'); const marker = mockHost.getReferenceMarkerFor(fileName, 'AppComponent');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);
@ -203,7 +203,7 @@ describe('hover', () => {
const content = mockHost.readFile(fileName) !; const content = mockHost.readFile(fileName) !;
const position = content.indexOf('StringModel'); const position = content.indexOf('StringModel');
expect(position).toBeGreaterThan(0); expect(position).toBeGreaterThan(0);
const quickInfo = ngLS.getHoverAt(fileName, position); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, position);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual({ expect(textSpan).toEqual({
@ -216,7 +216,7 @@ describe('hover', () => {
it('should be able to provide quick info for $any() cast function', () => { it('should be able to provide quick info for $any() cast function', () => {
const content = mockHost.override(TEST_TEMPLATE, '<div>{{$any(title)}}</div>'); const content = mockHost.override(TEST_TEMPLATE, '<div>{{$any(title)}}</div>');
const position = content.indexOf('$any'); const position = content.indexOf('$any');
const quickInfo = ngLS.getHoverAt(TEST_TEMPLATE, position); const quickInfo = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, position);
expect(quickInfo).toBeDefined(); expect(quickInfo).toBeDefined();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual({ expect(textSpan).toEqual({
@ -229,7 +229,7 @@ describe('hover', () => {
it('should provide documentation for a property', () => { it('should provide documentation for a property', () => {
mockHost.override(TEST_TEMPLATE, `<div>{{~{cursor}title}}</div>`); mockHost.override(TEST_TEMPLATE, `<div>{{~{cursor}title}}</div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const quickInfo = ngLS.getHoverAt(TEST_TEMPLATE, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, marker.start);
expect(quickInfo).toBeDefined(); expect(quickInfo).toBeDefined();
const documentation = toText(quickInfo !.documentation); const documentation = toText(quickInfo !.documentation);
expect(documentation).toBe('This is the title of the `TemplateReference` Component.'); expect(documentation).toBe('This is the title of the `TemplateReference` Component.');
@ -238,7 +238,7 @@ describe('hover', () => {
it('should provide documentation for a selector', () => { it('should provide documentation for a selector', () => {
mockHost.override(TEST_TEMPLATE, `<~{cursor}test-comp></test-comp>`); mockHost.override(TEST_TEMPLATE, `<~{cursor}test-comp></test-comp>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const quickInfo = ngLS.getHoverAt(TEST_TEMPLATE, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(TEST_TEMPLATE, marker.start);
expect(quickInfo).toBeDefined(); expect(quickInfo).toBeDefined();
const documentation = toText(quickInfo !.documentation); const documentation = toText(quickInfo !.documentation);
expect(documentation).toBe('This Component provides the `test-comp` selector.'); expect(documentation).toBe('This Component provides the `test-comp` selector.');
@ -253,7 +253,7 @@ describe('hover', () => {
name: string; name: string;
}`); }`);
const marker = mockHost.getReferenceMarkerFor(fileName, 'name'); const marker = mockHost.getReferenceMarkerFor(fileName, 'name');
const quickInfo = ngLS.getHoverAt(fileName, marker.start); const quickInfo = ngLS.getQuickInfoAtPosition(fileName, marker.start);
expect(quickInfo).toBeTruthy(); expect(quickInfo).toBeTruthy();
const {textSpan, displayParts} = quickInfo !; const {textSpan, displayParts} = quickInfo !;
expect(textSpan).toEqual(marker); expect(textSpan).toEqual(marker);

View File

@ -24,16 +24,17 @@ describe('service without angular', () => {
beforeEach(() => { mockHost.reset(); }); beforeEach(() => { mockHost.reset(); });
it('should not crash a get diagnostics', it('should not crash a get diagnostics',
() => { expect(() => ngService.getDiagnostics(fileName)).not.toThrow(); }); () => { expect(() => ngService.getSemanticDiagnostics(fileName)).not.toThrow(); });
it('should not crash a completion', it('should not crash a completion',
() => { expect(() => ngService.getCompletionsAt(fileName, position)).not.toThrow(); }); () => { expect(() => ngService.getCompletionsAtPosition(fileName, position)).not.toThrow(); });
it('should not crash a get definition', it('should not crash a get definition', () => {
() => { expect(() => ngService.getDefinitionAt(fileName, position)).not.toThrow(); }); expect(() => ngService.getDefinitionAndBoundSpan(fileName, position)).not.toThrow();
});
it('should not crash a hover', it('should not crash a hover',
() => { expect(() => ngService.getHoverAt(fileName, position)).not.toThrow(); }); () => { expect(() => ngService.getQuickInfoAtPosition(fileName, position)).not.toThrow(); });
it('should not crash with an incomplete class', () => { it('should not crash with an incomplete class', () => {
mockHost.addCode('\nexport class'); mockHost.addCode('\nexport class');