Skip to content

Commit

Permalink
fix(pug): more reliable completion at empty lines
Browse files Browse the repository at this point in the history
  • Loading branch information
johnsoncodehk committed Feb 20, 2023
1 parent 8700b68 commit 02f317b
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 41 deletions.
31 changes: 3 additions & 28 deletions packages/pug/src/baseParse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,19 @@ import { TextDocument } from 'vscode-languageserver-textdocument';

const pugParser = require('pug-parser');

export enum MappingKind {
EmptyTagCompletion,
}

export function baseParse(pugCode: string) {

const fileName = 'foo.pug';
const pugTextDocument = TextDocument.create('file:///a.pug', 'jade', 0, pugCode);
const codeGen: Segment<MappingKind | undefined>[] = [];
const codeGen: Segment<any>[] = [];
let error: {
code: string,
msg: string,
line: number,
column: number,
filename: string,
} | undefined;
let emptyLineEnds: ReturnType<typeof collectEmptyLineEnds>;
let emptyLineEnds: ReturnType<typeof collectEmptyLineEnds> = [];
let attrsBlocks: ReturnType<typeof collectAttrsBlocks>;
let ast: Node | undefined;

Expand All @@ -34,23 +30,10 @@ export function baseParse(pugCode: string) {
ast = pugParser(tokens, { filename: fileName, src: pugCode }) as Node;
visitNode(ast, undefined, undefined);

// support tag auto-complete in empty lines
for (const emptyLineEnd of emptyLineEnds) {
codeGen.push('<');
codeGen.push([
'x',
undefined,
emptyLineEnd,
MappingKind.EmptyTagCompletion,
]);
codeGen.push('x />');
}

codeGen.push([
'',
undefined,
pugCode.trimEnd().length,
undefined,
]);
}
catch (e) {
Expand All @@ -68,6 +51,7 @@ export function baseParse(pugCode: string) {
pugTextDocument,
error,
ast,
emptyLineEnds,
};

function visitNode(node: Node, next: Node | undefined, parent: Node | undefined) {
Expand All @@ -84,7 +68,6 @@ export function baseParse(pugCode: string) {
'',
undefined,
pugTagRange.start,
undefined,
]);

const selfClosing = node.block.nodes.length === 0;
Expand All @@ -97,15 +80,13 @@ export function baseParse(pugCode: string) {
'',
undefined,
pugTagRange.start,
undefined,
]);
}
else if (node.type === 'Text') {
codeGen.push([
node.val,
undefined,
getDocOffset(node.line, node.column),
undefined,
]);
}
}
Expand All @@ -114,7 +95,6 @@ export function baseParse(pugCode: string) {
'',
undefined,
getDocOffset(node.line, node.column),
undefined,
]);
codeGen.push('<');
const tagRange = getDocRange(node.line, node.column, node.name.length);
Expand All @@ -123,7 +103,6 @@ export function baseParse(pugCode: string) {
node.name,
undefined,
tagRange.start,
undefined,
]);
}
else {
Expand All @@ -148,7 +127,6 @@ export function baseParse(pugCode: string) {
attr.val,
undefined,
getDocOffset(attr.line, attr.column),
undefined
]);
}
}
Expand All @@ -159,7 +137,6 @@ export function baseParse(pugCode: string) {
attrsBlock.text,
undefined,
attrsBlock.offset,
undefined,
]);
}

Expand Down Expand Up @@ -188,7 +165,6 @@ export function baseParse(pugCode: string) {
'',
undefined,
nextStart,
undefined,
]);
}
codeGen.push(`</${node.name}>`);
Expand All @@ -206,7 +182,6 @@ export function baseParse(pugCode: string) {
attr.val.slice(1, -1), // remove "
undefined,
getDocOffset(attr.line, attr.column + 1),
undefined
]);
}
}
Expand Down
4 changes: 1 addition & 3 deletions packages/pug/src/pugDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ export function register(htmlLs: html.LanguageService) {
const htmlDocument = htmlLs.parseHTMLDocument(htmlTextDocument);

return {
pugTextDocument: parsed.pugTextDocument,
...parsed,
htmlTextDocument,
htmlDocument,
map: sourceMap,
error: parsed.error,
ast: parsed.ast,
};
};
}
25 changes: 23 additions & 2 deletions packages/pug/src/services/completion.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import { transformer } from '@volar/language-service';
import type * as html from 'vscode-html-languageservice';
import { MappingKind } from '../baseParse';
import { TextDocument } from 'vscode-html-languageservice';
import type { PugDocument } from '../pugDocument';

export function register(htmlLs: html.LanguageService) {

const docForEmptyLineCompletion = TextDocument.create('file:///foo.html', 'html', 0, '< />');
const htmlDocForEmptyLineCompletion = htmlLs.parseHTMLDocument(docForEmptyLineCompletion);
const posForEmptyLine = docForEmptyLineCompletion.positionAt(1);

return async (pugDoc: PugDocument, pos: html.Position, documentContext: html.DocumentContext | undefined, options?: html.CompletionConfiguration | undefined) => {

const htmlPos = pugDoc.map.toGeneratedPosition(pos, data => data !== MappingKind.EmptyTagCompletion);
const offset = pugDoc.pugTextDocument.offsetAt(pos);

if (pugDoc.emptyLineEnds.includes(offset)) {

const htmlComplete = htmlLs.doComplete(
docForEmptyLineCompletion,
posForEmptyLine,
htmlDocForEmptyLineCompletion,
options,
);
for (const item of htmlComplete.items) {
item.textEdit = undefined;
}
return htmlComplete;
}

const htmlPos = pugDoc.map.toGeneratedPosition(pos);
if (!htmlPos)
return;

Expand Down
3 changes: 1 addition & 2 deletions packages/pug/src/services/documentHighlight.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { transformer } from '@volar/language-service';
import type * as html from 'vscode-html-languageservice';
import { MappingKind } from '../baseParse';
import type { PugDocument } from '../pugDocument';

export function register(htmlLs: html.LanguageService) {
return (pugDoc: PugDocument, pos: html.Position) => {

const htmlPos = pugDoc.map.toGeneratedPosition(pos, data => data !== MappingKind.EmptyTagCompletion);
const htmlPos = pugDoc.map.toGeneratedPosition(pos);
if (!htmlPos)
return;

Expand Down
3 changes: 1 addition & 2 deletions packages/pug/src/services/hover.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { transformer } from '@volar/language-service';
import type * as html from 'vscode-html-languageservice';
import { MappingKind } from '../baseParse';
import type { PugDocument } from '../pugDocument';

export function register(htmlLs: html.LanguageService) {
return (pugDoc: PugDocument, pos: html.Position, options?: html.HoverSettings | undefined) => {

const htmlPos = pugDoc.map.toGeneratedPosition(pos, data => data !== MappingKind.EmptyTagCompletion);
const htmlPos = pugDoc.map.toGeneratedPosition(pos);
if (!htmlPos)
return;

Expand Down
3 changes: 1 addition & 2 deletions packages/pug/src/services/scanner.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import type * as html from 'vscode-html-languageservice';
import { MappingKind } from '../baseParse';
import type { PugDocument } from '../pugDocument';

export function register(htmlLs: html.LanguageService) {
return (pugDoc: PugDocument, initialOffset = 0) => {

const htmlOffset = pugDoc.map.map.mappings
.filter(mapping => mapping.sourceRange[0] >= initialOffset && mapping.data !== MappingKind.EmptyTagCompletion)
.filter(mapping => mapping.sourceRange[0] >= initialOffset)
.sort((a, b) => a.generatedRange[0] - b.generatedRange[0])[0]
?.generatedRange[0];

Expand Down
3 changes: 1 addition & 2 deletions packages/pug/src/services/selectionRanges.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { transformer } from '@volar/language-service';
import type * as html from 'vscode-html-languageservice';
import { MappingKind } from '../baseParse';
import type { PugDocument } from '../pugDocument';

export function register(htmlLs: html.LanguageService) {
return (pugDoc: PugDocument, posArr: html.Position[]) => {

const htmlPosArr = posArr
.map(position => pugDoc.map.toGeneratedPosition(position, data => data !== MappingKind.EmptyTagCompletion))
.map(position => pugDoc.map.toGeneratedPosition(position))
.filter((v): v is NonNullable<typeof v> => !!v);

const htmlResult = htmlLs.getSelectionRanges(
Expand Down

0 comments on commit 02f317b

Please sign in to comment.