-
Notifications
You must be signed in to change notification settings - Fork 528
Expand file tree
/
Copy pathlombokSupport.ts
More file actions
283 lines (262 loc) · 9.98 KB
/
lombokSupport.ts
File metadata and controls
283 lines (262 loc) · 9.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
'use strict';
import * as fse from "fs-extra";
import * as path from "path";
import * as semver from 'semver';
import * as vscode from "vscode";
import { ExtensionContext, window, commands, Uri } from "vscode";
import { Commands } from "./commands";
import { apiManager } from "./apiManager";
import { languageStatusBarProvider } from './runtimeStatusBarProvider';
import { logger } from './log';
import { getAllJavaProjects } from "./utils";
export const JAVA_LOMBOK_PATH = "java.lombokPath";
const languageServerDocumentSelector = [
{ scheme: 'file', language: 'java' },
{ scheme: 'jdt', language: 'java' },
{ scheme: 'untitled', language: 'java' },
{ pattern: '**/pom.xml' },
{ pattern: '**/{build,settings}.gradle'},
{ pattern: '**/{build,settings}.gradle.kts'}
];
const lombokJarRegex = /lombok-\d+.*\.jar$/;
const compatibleVersion = '1.18.4';
let activeLombokPath: string = undefined;
let isLombokStatusBarInitialized: boolean = false;
let isLombokCommandInitialized: boolean = false;
let isExtensionLombok: boolean = false; // whether use extension's Lombok or not
let projectLombokPath: string = undefined; // the project's Lombok classpath
export namespace Lombok {
export function getActiveLombokPath(): string | undefined {
return activeLombokPath;
}
}
export function isLombokSupportEnabled(): boolean {
return vscode.workspace.getConfiguration().get("java.jdt.ls.lombokSupport.enabled");
}
export function isLombokImported(): boolean {
return projectLombokPath!==undefined;
}
export function updateActiveLombokPath(path: string) {
activeLombokPath = path;
}
export function isLombokActive(context: ExtensionContext): boolean {
return activeLombokPath!==undefined;
}
export function cleanupLombokCache(context: ExtensionContext) {
context.workspaceState.update(JAVA_LOMBOK_PATH, undefined);
}
function getExtensionLombokPath(context: ExtensionContext): string {
if (!fse.pathExistsSync(context.asAbsolutePath("lombok"))) {
return undefined;
}
const files = fse.readdirSync(context.asAbsolutePath("lombok"));
if (!files.length) {
return undefined;
}
return path.join(context.asAbsolutePath("lombok"), files[0]);
}
function lombokPath2Version(lombokPath: string): string | undefined {
const match = lombokJarRegex.exec(lombokPath);
if (!match) {
return undefined;
}
const lombokVersion = match[0].split('.jar')[0];
return lombokVersion;
}
function lombokPath2VersionNumber(lombokPath: string): string | undefined {
const lombokVersion = lombokPath2Version(lombokPath);
if (!lombokVersion) {
return undefined;
}
const lombokVersionNumber = lombokVersion.split('-')[1];
return lombokVersionNumber;
}
export function getLombokVersion(): string | undefined {
return lombokPath2VersionNumber(activeLombokPath);
}
function isCompatibleLombokVersion(currentVersion: string | undefined): boolean {
return currentVersion && semver.gte(currentVersion, compatibleVersion);
}
export function addLombokParam(context: ExtensionContext, params: string[]) {
// Exclude user setting Lombok agent parameter
const reg = /-javaagent:.*[\\|/]lombok.*\.jar/;
const deleteIndex = [];
for (let i = 0; i < params.length; i++) {
if (reg.test(params[i])) {
deleteIndex.push(i);
}
}
for (let i = deleteIndex.length - 1; i >= 0; i--) {
params.splice(deleteIndex[i], 1);
}
// add -javaagent arg to support Lombok.
// use the extension's Lombok version by default.
isExtensionLombok = true;
let lombokJarPath: string = context.workspaceState.get(JAVA_LOMBOK_PATH);
if (lombokJarPath && fse.existsSync(lombokJarPath)) {
const lombokVersion = lombokPath2VersionNumber(lombokJarPath);
if (lombokVersion && isCompatibleLombokVersion(lombokVersion)) {
isExtensionLombok = false;
}
else {
cleanupLombokCache(context);
const extensionLombokVersion = lombokPath2VersionNumber(getExtensionLombokPath(context));
logger.warn(`The project's Lombok version ${lombokVersion || 'unknown'} is not supported, Falling back to the built-in Lombok version ${extensionLombokVersion || 'unknown'}`);
}
}
if (isExtensionLombok) {
lombokJarPath = getExtensionLombokPath(context);
}
// check if the Lombok.jar exists.
if (!lombokJarPath) {
logger.warn("Could not find lombok.jar path.");
return;
}
const lombokAgentParam = `-javaagent:${lombokJarPath}`;
params.push(lombokAgentParam);
updateActiveLombokPath(lombokJarPath);
}
export async function checkLombokDependency(context: ExtensionContext, projectUri?: Uri) {
if (!isLombokSupportEnabled()) {
return;
}
let versionChange: boolean = false;
let lombokFound: boolean = false;
let currentLombokVersion: string = undefined;
let previousLombokVersion: string = undefined;
let currentLombokClasspath: string = undefined;
const projectUris: string[] = projectUri ? [projectUri.toString()] : await getAllJavaProjects();
for (const projectUri of projectUris) {
const classpathResult = await apiManager.getApiInstance().getClasspaths(projectUri, {scope: 'test'});
for (const classpath of classpathResult.classpaths) {
if (lombokJarRegex.test(classpath)) {
currentLombokClasspath = classpath;
if (activeLombokPath && !isExtensionLombok) {
currentLombokVersion = lombokJarRegex.exec(classpath)[0];
previousLombokVersion = lombokJarRegex.exec(activeLombokPath)[0];
if (currentLombokVersion !== previousLombokVersion) {
versionChange = true;
}
}
lombokFound = true;
break;
}
}
if (lombokFound) {
break;
}
}
projectLombokPath = currentLombokClasspath;
/* if projectLombokPath is undefined, it means that this project has not imported Lombok.
* We don't need initialize Lombok status bar in this case.
*/
if (!isLombokStatusBarInitialized && projectLombokPath) {
if (!isLombokCommandInitialized) {
registerLombokConfigureCommand(context);
isLombokCommandInitialized = true;
}
languageStatusBarProvider.initializeLombokStatusBar();
isLombokStatusBarInitialized = true;
}
if (isLombokStatusBarInitialized && !projectLombokPath) {
languageStatusBarProvider.destroyLombokStatusBar();
isLombokStatusBarInitialized = false;
cleanupLombokCache(context);
}
if (versionChange && !isExtensionLombok) {
context.workspaceState.update(JAVA_LOMBOK_PATH, currentLombokClasspath);
const msg = `Lombok version changed from ${previousLombokVersion.split('.jar')[0].split('-')[1]} to ${currentLombokVersion.split('.jar')[0].split('-')[1]} \
. Do you want to reload the window to load the new Lombok version?`;
const action = 'Reload';
const restartId = Commands.RELOAD_WINDOW;
window.showInformationMessage(msg, action).then((selection) => {
if (action === selection) {
commands.executeCommand(restartId);
}
});
}
}
export function registerLombokConfigureCommand(context: ExtensionContext) {
context.subscriptions.push(commands.registerCommand(Commands.LOMBOK_CONFIGURE, async (buildFilePath: string) => {
const extensionLombokPath: string = getExtensionLombokPath(context);
if (!extensionLombokPath || !projectLombokPath) {
return;
}
const extensionItemLabel = 'Use Extension\'s Version';
const extensionItemLabelCheck = `• ${extensionItemLabel}`;
const projectItemLabel = 'Use Project\'s Version';
const projectItemLabelCheck = `• ${projectItemLabel}`;
const lombokPathItems = [
{
label: isExtensionLombok? extensionItemLabelCheck : extensionItemLabel,
description: `Lombok ${lombokPath2VersionNumber(extensionLombokPath) || 'unknown'}`
},
{
label: isExtensionLombok? projectItemLabel : projectItemLabelCheck,
description: `Lombok ${lombokPath2VersionNumber(projectLombokPath) || 'unknown'}`,
detail: projectLombokPath
}
];
const selectLombokPathItem = await window.showQuickPick(lombokPathItems, {
placeHolder: 'Select the Lombok version used in the Java extension'
});
let shouldReload: boolean = false;
if (!selectLombokPathItem) {
return;
}
if (selectLombokPathItem.label === extensionItemLabel || selectLombokPathItem.label === extensionItemLabelCheck) {
if (!isExtensionLombok) {
shouldReload = true;
cleanupLombokCache(context);
}
}
else {
if (isExtensionLombok) {
const projectLombokVersion = lombokPath2VersionNumber(projectLombokPath);
if (!isCompatibleLombokVersion(projectLombokVersion)) {
const msg = `The project's Lombok version ${projectLombokVersion || 'unknown'} is not supported. Falling back to the built-in Lombok version in the extension.`;
window.showWarningMessage(msg);
return;
}
else {
shouldReload = true;
context.workspaceState.update(JAVA_LOMBOK_PATH, projectLombokPath);
}
}
}
if (shouldReload) {
const msg = `The Lombok version used in Java extension has changed, please reload the window.`;
const action = 'Reload';
const restartId = Commands.RELOAD_WINDOW;
window.showInformationMessage(msg, action).then((selection) => {
if (action === selection) {
commands.executeCommand(restartId);
}
});
}
else {
const msg = `Current Lombok version is ${isExtensionLombok?'extension\'s' : 'project\'s'} version. Nothing to do.`;
window.showInformationMessage(msg);
}
}));
}
export namespace LombokVersionItemFactory {
export function create(version: string): vscode.LanguageStatusItem {
const item = vscode.languages.createLanguageStatusItem("javaLombokVersionItem", languageServerDocumentSelector);
item.severity = vscode.LanguageStatusSeverity?.Information;
item.name = "Lombok Version";
update(item, version);
item.command = getLombokChangeCommand();
return item;
}
export function update(item: any, version: string | undefined): void {
item.text = `Lombok ${version || 'unknown'}`;
}
function getLombokChangeCommand(): vscode.Command {
return {
title: `Configure Version`,
command: Commands.LOMBOK_CONFIGURE,
tooltip: `Configure Lombok Version`
};
}
}