Skip to content

Commit

Permalink
fixup! feat(language-service): add support for text replacement
Browse files Browse the repository at this point in the history
  • Loading branch information
ayazhafiz committed Oct 14, 2019
1 parent a07b3ed commit a3268cc
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 15 deletions.
11 changes: 9 additions & 2 deletions packages/language-service/src/completions.ts
Expand Up @@ -32,11 +32,14 @@ function getClosestTextStartOffset(templateInfo: AstResult, position: number): n
const {htmlAst, templateAst, template} = templateInfo;
const templatePosition = position - template.span.start;
const templatePath = findTemplateAstAt(templateInfo.templateAst, templatePosition);
// Closest HTML template AST node to the queried template position, like an element or attribute.
const templateAstTail = templatePath.tail;
if (!templateAstTail) {
return 0;
}

// If the closest HTML template node has a Angular template syntax AST inside it, extract it.
// Otherwise, get the text of the HTML template node, which is the closest starting text offset.
const ast: AST|string = templateAstTail.visit(
{
visitNgContent: () => '',
Expand All @@ -53,15 +56,17 @@ function getClosestTextStartOffset(templateInfo: AstResult, position: number): n
visitDirectiveProperty: ast => ast.value,
},
null);

if (!(ast instanceof AST)) {
return ast.length;
return ast.length; // offset of HTML template node text
}

// Find the Angular template syntax AST closest to queried template position.
const closestAst = findAstAt(ast, templatePosition - templateAstTail.sourceSpan.start.offset);
const closestTail = closestAst.tail;
if (!closestTail) return 0;

// Return the closest starting text offset in the template syntax AST, which is either the value
// of the AST or nothing at all.
return closestTail.visit({
visitBinary: ast => 0,
visitChain: ast => 0,
Expand Down Expand Up @@ -152,6 +157,8 @@ export function getTemplateCompletions(
null);
}

// Define the span of the partial word the completion query was called on, which will be replaced
// by a selected completion.
const offset = getClosestTextStartOffset(templateInfo, position);
return result.map(entry => {
return {
Expand Down
25 changes: 12 additions & 13 deletions packages/language-service/test/completions_spec.ts
Expand Up @@ -96,12 +96,12 @@ describe('completions', () => {
obj: {key: 'value'};
}
`);
const location = mockHost.getMarkerLocations(fileName) !['key'];
const completions = ngService.getCompletionsAt(fileName, location) !;
const location = mockHost.getLocationMarkerFor(fileName, 'key');
const completions = ngService.getCompletionsAt(fileName, location.start) !;
expect(completions).toBeDefined();
expect(completions.entries.length).toBe(1);
const [completion] = completions.entries;
expect(completion.replacementSpan).toEqual({start: location, length: 0});
expect(completion.replacementSpan).toEqual({start: location.start, length: 0});
});

it('should work for interpolations', () => {
Expand All @@ -116,12 +116,12 @@ describe('completions', () => {
title: string;
}
`);
const location = mockHost.getMarkerLocations(fileName) !['title'];
const completions = ngService.getCompletionsAt(fileName, location) !;
const location = mockHost.getLocationMarkerFor(fileName, 'title');
const completions = ngService.getCompletionsAt(fileName, location.start) !;
expect(completions).toBeDefined();
expect(completions.entries.length).toBe(1);
const [completion] = completions.entries;
expect(completion.replacementSpan).toEqual({start: location - 2, length: 2});
expect(completion.replacementSpan).toEqual({start: location.start - 2, length: 2});
});

it('should work for attributes', () => {
Expand All @@ -136,12 +136,12 @@ describe('completions', () => {
title: string;
}
`);
const location = mockHost.getMarkerLocations(fileName) !['click'];
const completions = ngService.getCompletionsAt(fileName, location) !;
const location = mockHost.getLocationMarkerFor(fileName, 'click');
const completions = ngService.getCompletionsAt(fileName, location.start) !;
expect(completions).toBeDefined();
const completion = completions.entries.find(entry => entry.name === '(click)') !;
expect(completion).toBeDefined();
expect(completion.replacementSpan).toEqual({start: location - 2, length: 2});
expect(completion.replacementSpan).toEqual({start: location.start - 2, length: 2});
});

it('should work for events', () => {
Expand All @@ -156,13 +156,12 @@ describe('completions', () => {
handleClick() {}
}
`);
const location = mockHost.getMarkerLocations(fileName) !['handleClick'];
debugger;
const completions = ngService.getCompletionsAt(fileName, location) !;
const location = mockHost.getLocationMarkerFor(fileName, 'handleClick');
const completions = ngService.getCompletionsAt(fileName, location.start) !;
expect(completions).toBeDefined();
expect(completions.entries.length).toBe(1);
const [completion] = completions.entries;
expect(completion.replacementSpan).toEqual({start: location - 3, length: 3});
expect(completion.replacementSpan).toEqual({start: location.start - 3, length: 3});
});
});

Expand Down

0 comments on commit a3268cc

Please sign in to comment.