Skip to content

Commit aa77e84

Browse files
committed
refactor: next
1 parent aca4ae7 commit aa77e84

File tree

1 file changed

+144
-39
lines changed

1 file changed

+144
-39
lines changed

src/decorator.ts

Lines changed: 144 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,50 @@
11
import * as vscode from "vscode";
22
import { genMarkdownString, getColorTokenValue } from "./utils";
33

4+
interface DecorationItem {
5+
line: number;
6+
disposable: vscode.TextEditorDecorationType;
7+
}
8+
49
export default function setupChangeEvent(
510
context: vscode.ExtensionContext,
611
fullToken: any
712
) {
813
let timeout: NodeJS.Timer | undefined = undefined;
914
let activeEditor = vscode.window.activeTextEditor;
1015
const fullTokenKeys = Object.keys(fullToken);
11-
const decorationSet = new Set<vscode.TextEditorDecorationType>();
16+
const fileDecorationMap = new Map<string, DecorationItem[]>();
17+
const openedFileNameSet = new Set<string>();
18+
let lineCount = 0;
1219

1320
if (activeEditor) {
14-
triggerUpdateDecorations();
21+
lineCount = activeEditor.document.lineCount;
22+
const isOpened = checkOpenedFile(activeEditor.document.fileName);
23+
24+
if (!isOpened) {
25+
triggerUpdateDecorations();
26+
}
1527
}
1628

1729
vscode.workspace.onDidChangeTextDocument(
1830
(event) => {
31+
if (event.contentChanges.length === 0) {
32+
return;
33+
}
34+
35+
const startLine = event.contentChanges[0].range.start.line;
36+
let endLine = event.contentChanges[0].range.end.line;
37+
1938
if (activeEditor && event.document === activeEditor.document) {
20-
triggerUpdateDecorations(true);
39+
/**
40+
* As undo (reason === 1) or redo (reason === 2) are very fast, do it very fast too.
41+
* Same as `delete` some code
42+
*/
43+
const throttle =
44+
event.reason !== undefined
45+
? false
46+
: event.document.lineCount - lineCount >= 0;
47+
triggerUpdateDecorations(throttle, true, startLine, endLine);
2148
}
2249
},
2350
null,
@@ -28,78 +55,156 @@ export default function setupChangeEvent(
2855
(editor) => {
2956
activeEditor = editor;
3057
if (editor) {
31-
triggerUpdateDecorations();
58+
lineCount = editor.document.lineCount;
59+
const isOpened = checkOpenedFile(editor.document.fileName);
60+
61+
if (!isOpened) {
62+
triggerUpdateDecorations();
63+
}
3264
}
3365
},
3466
null,
3567
context.subscriptions
3668
);
3769

38-
function triggerUpdateDecorations(throttle = false) {
70+
function triggerUpdateDecorations(
71+
throttle = false,
72+
isEdit = false,
73+
startLine?: number,
74+
endLine?: number
75+
) {
3976
if (timeout) {
4077
clearTimeout(timeout);
4178
timeout = undefined;
4279
}
4380
if (throttle) {
44-
timeout = setTimeout(updateDecorations, 500);
81+
timeout = setTimeout(() => {
82+
updateDecorations(isEdit, startLine, endLine);
83+
}, 500);
4584
} else {
46-
updateDecorations();
85+
updateDecorations(isEdit, startLine, endLine);
4786
}
4887
}
4988

50-
function updateDecorations() {
89+
function updateDecorations(
90+
isEdit: boolean,
91+
startLine?: number,
92+
endLine?: number
93+
) {
5194
if (activeEditor) {
95+
console.log("!!!!!!update!!!!", startLine, endLine);
5296
const text = activeEditor.document.getText();
53-
decorationSet.forEach((value) => {
54-
value.dispose();
55-
});
97+
const fileName = activeEditor.document.fileName;
98+
99+
if (!fileDecorationMap.has(fileName)) {
100+
fileDecorationMap.set(fileName, []);
101+
}
102+
103+
const currentFileDecorations = fileDecorationMap.get(fileName) || [];
104+
const currentLineCount = activeEditor.document.lineCount;
105+
const diffLine = currentLineCount - lineCount;
106+
console.log("diffLine", diffLine);
107+
lineCount = currentLineCount;
108+
109+
/**
110+
* Dispose the line decoration between start and end
111+
*/
112+
if (
113+
startLine &&
114+
endLine &&
115+
currentFileDecorations.length &&
116+
diffLine <= 0
117+
) {
118+
for (let i = startLine; i <= endLine; i++) {
119+
for (let j = 0; j < currentFileDecorations.length; j++) {
120+
if (currentFileDecorations[j].line === i) {
121+
currentFileDecorations[j].disposable.dispose();
122+
console.log("dispose", i);
123+
currentFileDecorations.splice(j--, 1);
124+
}
125+
}
126+
}
127+
}
128+
129+
// if (diffLine > 0) {
130+
// return;
131+
// }
56132

57133
fullTokenKeys.forEach((key: string) => {
58134
if (!activeEditor) {
59135
return;
60136
}
137+
61138
const regEx = new RegExp(`\\b(${key})\\b(?!-)`, "g");
62139

63140
let match;
64141
while ((match = regEx.exec(text))) {
65142
const valueDecorations: vscode.DecorationOptions[] = [];
66143
let decorationType: vscode.TextEditorDecorationType;
67144

145+
/**
146+
* TIPS:
147+
* Actually, they are always at the same line.
148+
*/
68149
const startPos = activeEditor.document.positionAt(match.index);
69150
const endPos = activeEditor.document.positionAt(
70151
match.index + match[0].length
71152
);
153+
const currentLine = startPos.line;
72154

73-
const value = String(fullToken[key]);
74-
const colorSpan = genMarkdownString(value);
75-
const markDownString = new vscode.MarkdownString(
76-
`<h3>antd design token: ${match[0]}</h3>${colorSpan}<code>${value}</code><br></br>`
77-
);
78-
markDownString.supportHtml = true;
79-
markDownString.isTrusted = true;
80-
81-
const decoration = {
82-
range: new vscode.Range(startPos, endPos),
83-
hoverMessage: markDownString,
84-
};
85-
86-
const colorValue = getColorTokenValue(fullToken[key]);
87-
valueDecorations.push(decoration);
88-
89-
decorationType = vscode.window.createTextEditorDecorationType({
90-
after: {
91-
contentText: colorValue ? `**` : `(${String(fullToken[key])})`,
92-
backgroundColor: colorValue || "",
93-
margin: "0 0 0 4px;",
94-
color: colorValue || "#1890ff",
95-
fontWeight: "bolder",
96-
},
97-
});
98-
99-
decorationSet.add(decorationType);
100-
activeEditor.setDecorations(decorationType, valueDecorations);
155+
if (
156+
!isEdit ||
157+
// diffLine > 0 ||
158+
(startLine &&
159+
endLine &&
160+
currentLine >= startLine &&
161+
currentLine <= endLine)
162+
) {
163+
const value = String(fullToken[key]);
164+
const colorSpan = genMarkdownString(value);
165+
const markDownString = new vscode.MarkdownString(
166+
`<h3>antd design token: ${match[0]}</h3>${colorSpan}<code>${value}</code><br></br>`
167+
);
168+
markDownString.supportHtml = true;
169+
markDownString.isTrusted = true;
170+
171+
const decoration = {
172+
range: new vscode.Range(startPos, endPos),
173+
hoverMessage: markDownString,
174+
};
175+
176+
const colorValue = getColorTokenValue(fullToken[key]);
177+
valueDecorations.push(decoration);
178+
179+
decorationType = vscode.window.createTextEditorDecorationType({
180+
after: {
181+
contentText: colorValue ? `**` : `(${String(fullToken[key])})`,
182+
backgroundColor: colorValue || "",
183+
margin: "0 0 0 4px;",
184+
color: colorValue || "#1890ff",
185+
fontWeight: "bolder",
186+
},
187+
});
188+
189+
currentFileDecorations.push({
190+
line: currentLine,
191+
disposable: decorationType,
192+
});
193+
console.log("setDecorations", currentLine);
194+
activeEditor.setDecorations(decorationType, valueDecorations);
195+
}
101196
}
102197
});
198+
fileDecorationMap.set(fileName, currentFileDecorations);
199+
}
200+
}
201+
202+
function checkOpenedFile(fileName: string): boolean {
203+
if (openedFileNameSet.has(fileName)) {
204+
return true;
205+
} else {
206+
openedFileNameSet.add(fileName);
207+
return false;
103208
}
104209
}
105210
}

0 commit comments

Comments
 (0)