fix(language-service): Add directive selectors & banana-in-a-box to completions (#33311)
This commit refactors attribute completions and fixes two bugs: 1. selectors for directives are not provided 2. banana-in-a-box (two way binding) syntax are not provided PR closes https://github.com/angular/vscode-ng-language-service/issues/358 PR Close #33311
This commit is contained in:

committed by
Andrew Kushnir

parent
c0b90c2010
commit
49eec5d872
@ -40,7 +40,7 @@ describe('completions', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should be able to return element directives', () => {
|
||||
it('should be able to return component directives', () => {
|
||||
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'empty');
|
||||
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start);
|
||||
expectContain(completions, CompletionKind.COMPONENT, [
|
||||
@ -51,6 +51,12 @@ describe('completions', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should be able to return attribute directives', () => {
|
||||
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'h1-after-space');
|
||||
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start);
|
||||
expectContain(completions, CompletionKind.ATTRIBUTE, ['string-model', 'number-model']);
|
||||
});
|
||||
|
||||
it('should be able to return angular pseudo elements', () => {
|
||||
const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'empty');
|
||||
const completions = ngLS.getCompletionsAt(APP_COMPONENT, marker.start);
|
||||
@ -279,7 +285,18 @@ describe('completions', () => {
|
||||
expectContain(completions, CompletionKind.METHOD, ['modelChanged']);
|
||||
});
|
||||
|
||||
it('should be able to complete a two-way binding', () => {
|
||||
it('should be able to complete a the LHS of a two-way binding', () => {
|
||||
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'two-way-binding-input');
|
||||
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start);
|
||||
expectContain(completions, CompletionKind.ATTRIBUTE, [
|
||||
'ngModel',
|
||||
'[ngModel]',
|
||||
'(ngModelChange)',
|
||||
'[(ngModel)]',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should be able to complete a the RHS of a two-way binding', () => {
|
||||
const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'two-way-binding-model');
|
||||
const completions = ngLS.getCompletionsAt(PARSING_CASES, marker.start);
|
||||
expectContain(completions, CompletionKind.PROPERTY, ['test']);
|
||||
@ -288,7 +305,7 @@ describe('completions', () => {
|
||||
it('should work with input and output', () => {
|
||||
const m1 = mockHost.getLocationMarkerFor(PARSING_CASES, 'string-marker');
|
||||
const c1 = ngLS.getCompletionsAt(PARSING_CASES, m1.start);
|
||||
expectContain(c1, CompletionKind.ATTRIBUTE, ['[model]', '(model)']);
|
||||
expectContain(c1, CompletionKind.ATTRIBUTE, ['[model]', '(modelChange)', '[(model)]']);
|
||||
|
||||
const m2 = mockHost.getLocationMarkerFor(PARSING_CASES, 'number-marker');
|
||||
const c2 = ngLS.getCompletionsAt(PARSING_CASES, m2.start);
|
||||
@ -347,7 +364,7 @@ describe('completions', () => {
|
||||
function expectContain(
|
||||
completions: ts.CompletionInfo | undefined, kind: CompletionKind, names: string[]) {
|
||||
expect(completions).toBeDefined();
|
||||
expect(completions !.entries).toEqual(jasmine.arrayContaining(names.map(name => {
|
||||
return jasmine.objectContaining({name, kind});
|
||||
}) as any));
|
||||
for (const name of names) {
|
||||
expect(completions !.entries).toContain(jasmine.objectContaining({ name, kind } as any));
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,9 @@ export class EventBinding {
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: '<h1 [(model)]="~{two-way-binding-model}test"></h1>',
|
||||
template: `
|
||||
<h1 [(model)]="~{two-way-binding-model}test"></h1>
|
||||
<input ~{two-way-binding-input}></input>`,
|
||||
})
|
||||
export class TwoWayBinding {
|
||||
test: string = 'test';
|
||||
@ -80,7 +82,7 @@ export class TwoWayBinding {
|
||||
})
|
||||
export class StringModel {
|
||||
@Input() model: string = 'model';
|
||||
@Output() modelChanged: EventEmitter<string> = new EventEmitter();
|
||||
@Output() modelChange: EventEmitter<string> = new EventEmitter();
|
||||
}
|
||||
|
||||
@Directive({
|
||||
@ -88,7 +90,7 @@ export class StringModel {
|
||||
})
|
||||
export class NumberModel {
|
||||
@Input('inputAlias') model: number = 0;
|
||||
@Output('outputAlias') modelChanged: EventEmitter<number> = new EventEmitter();
|
||||
@Output('outputAlias') modelChange: EventEmitter<number> = new EventEmitter();
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
Reference in New Issue
Block a user