Skip to content

Commit bd54451

Browse files
committed
Ignore comments when select next/prev. Fixes microsoft#27763
1 parent a53cce9 commit bd54451

4 files changed

Lines changed: 69 additions & 56 deletions

File tree

extensions/emmet/src/selectItem.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ export function fetchSelectItem(direction: string): void {
3434
let rootNode: Node = parseContent(editor.document.getText());
3535
let newSelections: vscode.Selection[] = [];
3636
editor.selections.forEach(selection => {
37-
let updatedSelection = direction === 'next' ? nextItem(selection, editor, rootNode) : prevItem(selection, editor, rootNode);
37+
const selectionStart = editor.document.offsetAt(selection.isReversed ? selection.active : selection.anchor);
38+
const selectionEnd = editor.document.offsetAt(selection.isReversed ? selection.anchor : selection.active);
39+
40+
let updatedSelection = direction === 'next' ? nextItem(selectionStart, selectionEnd, editor, rootNode) : prevItem(selectionStart, selectionEnd, editor, rootNode);
3841
newSelections.push(updatedSelection ? updatedSelection : selection);
3942
});
4043
editor.selections = newSelections;

extensions/emmet/src/selectItemHTML.ts

Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,90 +7,104 @@ import * as vscode from 'vscode';
77
import { getNode, getDeepestNode, findNextWord, findPrevWord } from './util';
88
import Node from '@emmetio/node';
99

10-
export function nextItemHTML(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
11-
let offset = editor.document.offsetAt(selection.active);
12-
let currentNode = getNode(rootNode, offset);
10+
export function nextItemHTML(selectionStart: number, selectionEnd: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
11+
let currentNode = getNode(rootNode, selectionEnd);
12+
let nextNode: Node;
13+
14+
if (currentNode.type !== 'comment') {
15+
// If cursor is in the tag name, select tag
16+
if (selectionEnd < currentNode.open.start + currentNode.name.length) {
17+
return getSelectionFromNode(currentNode, editor.document);
18+
}
1319

14-
// Cursor is in the open tag, look for attributes
15-
if (offset < currentNode.open.end) {
16-
let attrSelection = getNextAttribute(selection, editor.document, currentNode);
17-
if (attrSelection) {
18-
return attrSelection;
20+
// If cursor is in the open tag, look for attributes
21+
if (selectionEnd < currentNode.open.end) {
22+
let attrSelection = getNextAttribute(selectionStart, selectionEnd, editor.document, currentNode);
23+
if (attrSelection) {
24+
return attrSelection;
25+
}
1926
}
20-
}
2127

22-
// Get the first child of current node which is right after the cursor
23-
let nextNode = currentNode.firstChild;
24-
while (nextNode && nextNode.start < offset) {
25-
nextNode = nextNode.nextSibling;
28+
// Get the first child of current node which is right after the cursor and is not a comment
29+
nextNode = currentNode.firstChild;
30+
while (nextNode && (nextNode.start < selectionEnd || nextNode.type === 'comment')) {
31+
nextNode = nextNode.nextSibling;
32+
}
2633
}
2734

28-
// Get next sibling of current node or the parent
35+
36+
// Get next sibling of current node which is not a comment. If none is found try the same on the parent
2937
while (!nextNode && currentNode) {
30-
nextNode = currentNode.nextSibling;
31-
currentNode = currentNode.parent;
38+
if (currentNode.nextSibling) {
39+
if (currentNode.nextSibling.type !== 'comment') {
40+
nextNode = currentNode.nextSibling;
41+
} else {
42+
currentNode = currentNode.nextSibling;
43+
}
44+
} else {
45+
currentNode = currentNode.parent;
46+
}
3247
}
3348

3449
return getSelectionFromNode(nextNode, editor.document);
3550
}
3651

37-
export function prevItemHTML(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
38-
let offset = editor.document.offsetAt(selection.active);
39-
let currentNode = getNode(rootNode, offset);
52+
export function prevItemHTML(selectionStart: number, selectionEnd: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
53+
let currentNode = getNode(rootNode, selectionStart);
4054
let prevNode: Node;
4155

42-
// Cursor is in the open tag after the tag name
43-
if (offset > currentNode.open.start + currentNode.name.length + 1 && offset <= currentNode.open.end) {
44-
prevNode = currentNode;
45-
}
56+
if (currentNode.type !== 'comment' && selectionStart > currentNode.open.start + 1) {
4657

47-
// Cursor is inside the tag
48-
if (!prevNode && offset > currentNode.open.end) {
49-
if (!currentNode.firstChild) {
50-
// No children, so current node should be selected
58+
if (selectionStart < currentNode.open.end || !currentNode.firstChild) {
5159
prevNode = currentNode;
5260
} else {
53-
// Select the child that appears just before the cursor
61+
// Select the child that appears just before the cursor and is not a comment
5462
prevNode = currentNode.firstChild;
55-
while (prevNode.nextSibling && prevNode.nextSibling.end < offset) {
63+
let oldOption: Node;
64+
while (prevNode.nextSibling && prevNode.nextSibling.end < selectionStart) {
65+
if (prevNode && prevNode.type !== 'comment') {
66+
oldOption = prevNode;
67+
}
5668
prevNode = prevNode.nextSibling;
5769
}
58-
if (prevNode) {
59-
prevNode = getDeepestNode(prevNode);
60-
}
70+
71+
prevNode = getDeepestNode((prevNode && prevNode.type !== 'comment') ? prevNode : oldOption);
6172
}
6273
}
6374

64-
if (!prevNode && currentNode.previousSibling) {
65-
prevNode = getDeepestNode(currentNode.previousSibling);
66-
}
75+
// Select previous sibling which is not a comment. If none found, then select parent
76+
while (!prevNode && currentNode) {
77+
if (currentNode.previousSibling) {
78+
if (currentNode.previousSibling.type !== 'comment') {
79+
prevNode = getDeepestNode(currentNode.previousSibling);
80+
} else {
81+
currentNode = currentNode.previousSibling;
82+
}
83+
} else {
84+
prevNode = currentNode.parent;
85+
}
6786

68-
if (!prevNode && currentNode.parent) {
69-
prevNode = currentNode.parent;
7087
}
7188

72-
let attrSelection = getPrevAttribute(selection, editor.document, prevNode);
89+
let attrSelection = getPrevAttribute(selectionStart, selectionEnd, editor.document, prevNode);
7390
return attrSelection ? attrSelection : getSelectionFromNode(prevNode, editor.document);
7491
}
7592

7693
function getSelectionFromNode(node: Node, document: vscode.TextDocument): vscode.Selection {
7794
if (node && node.open) {
7895
let selectionStart = document.positionAt(node.open.start + 1);
79-
let selectionEnd = node.type === 'comment' ? document.positionAt(node.open.end - 1) : selectionStart.translate(0, node.name.length);
96+
let selectionEnd = selectionStart.translate(0, node.name.length);
8097

8198
return new vscode.Selection(selectionStart, selectionEnd);
8299
}
83100
}
84101

85-
function getNextAttribute(selection: vscode.Selection, document: vscode.TextDocument, node: Node): vscode.Selection {
102+
function getNextAttribute(selectionStart: number, selectionEnd: number, document: vscode.TextDocument, node: Node): vscode.Selection {
86103

87104
if (!node.attributes || node.attributes.length === 0 || node.type === 'comment') {
88105
return;
89106
}
90107

91-
let selectionStart = document.offsetAt(selection.anchor);
92-
let selectionEnd = document.offsetAt(selection.active);
93-
94108
for (let i = 0; i < node.attributes.length; i++) {
95109
let attr = node.attributes[i];
96110

@@ -136,15 +150,12 @@ function getNextAttribute(selection: vscode.Selection, document: vscode.TextDocu
136150
}
137151
}
138152

139-
function getPrevAttribute(selection: vscode.Selection, document: vscode.TextDocument, node: Node): vscode.Selection {
153+
function getPrevAttribute(selectionStart: number, selectionEnd: number, document: vscode.TextDocument, node: Node): vscode.Selection {
140154

141155
if (!node.attributes || node.attributes.length === 0 || node.type === 'comment') {
142156
return;
143157
}
144158

145-
let selectionStart = document.offsetAt(selection.anchor);
146-
let selectionEnd = document.offsetAt(selection.active);
147-
148159
for (let i = node.attributes.length - 1; i >= 0; i--) {
149160
let attr = node.attributes[i];
150161

extensions/emmet/src/selectItemStylesheet.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import * as vscode from 'vscode';
77
import { getNode, getDeepestNode, findNextWord, findPrevWord } from './util';
88
import Node from '@emmetio/node';
99

10-
export function nextItemStylesheet(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
11-
let startOffset = editor.document.offsetAt(selection.anchor);
12-
let endOffset = editor.document.offsetAt(selection.active);
10+
export function nextItemStylesheet(startOffset: number, endOffset: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
1311
let currentNode = getNode(rootNode, endOffset, true);
1412

1513
// Full property is selected, so select full property value next
@@ -47,9 +45,7 @@ export function nextItemStylesheet(selection: vscode.Selection, editor: vscode.T
4745

4846
}
4947

50-
export function prevItemStylesheet(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
51-
let startOffset = editor.document.offsetAt(selection.anchor);
52-
let endOffset = editor.document.offsetAt(selection.active);
48+
export function prevItemStylesheet(startOffset: number, endOffset: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
5349
let currentNode = getNode(rootNode, startOffset);
5450
if (!currentNode) {
5551
currentNode = rootNode;

extensions/emmet/src/util.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,11 @@ export function getDeepestNode(node: Node): Node {
134134
if (!node || !node.children || node.children.length === 0) {
135135
return node;
136136
}
137-
138-
return getDeepestNode(node.children[node.children.length - 1]);
137+
for (let i = node.children.length - 1; i >= 0; i--) {
138+
if (node.children[i].type !== 'comment') {
139+
return getDeepestNode(node.children[i]);
140+
}
141+
}
139142
}
140143

141144
export function findNextWord(propertyValue: string, pos: number): [number, number] {

0 commit comments

Comments
 (0)