Skip to content

Commit ce9c5a7

Browse files
authored
Provide reload project code action on demand (#2575)
- The reload project code actions will be provided for the related diagnostics. Signed-off-by: Sheng Chen <[email protected]>
1 parent 550f57e commit ce9c5a7

File tree

5 files changed

+115
-35
lines changed

5 files changed

+115
-35
lines changed

src/gradle/gradleCodeActionProvider.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as fse from "fs-extra";
44
import * as path from "path";
55
import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, CodeActionProvider, CodeActionProviderMetadata, Command, commands, Diagnostic, DiagnosticRelatedInformation, ExtensionContext, ProviderResult, Range, Selection, TextDocument, Uri } from "vscode";
66
import { Commands } from "../commands";
7-
import { upgradeGradle } from "../standardLanguageClient";
7+
import { upgradeGradle } from "../standardLanguageClientUtils";
88

99
export class GradleCodeActionProvider implements CodeActionProvider<CodeAction> {
1010

@@ -29,6 +29,17 @@ export class GradleCodeActionProvider implements CodeActionProvider<CodeAction>
2929
private async provideGradleCodeActions(document: TextDocument, diagnostics: readonly Diagnostic[]): Promise<CodeAction[]> {
3030
const codeActions = [];
3131
for (const diagnostic of diagnostics) {
32+
if (diagnostic.message?.startsWith("The build file has been changed")) {
33+
const reloadProjectAction = new CodeAction("Reload project", CodeActionKind.QuickFix);
34+
reloadProjectAction.command = {
35+
title: "Reload Project",
36+
command: Commands.CONFIGURATION_UPDATE,
37+
arguments: [document.uri],
38+
};
39+
codeActions.push(reloadProjectAction);
40+
continue;
41+
}
42+
3243
const documentUri = document.uri.toString();
3344
if (documentUri.endsWith(GradleCodeActionProvider.WRAPPER_PROPERTIES_DESCRIPTOR) && diagnostic.code === GradleCodeActionProvider.GRADLE_INVALID_TYPE_CODE_ID.toString()) {
3445
const projectPath = path.resolve(Uri.parse(documentUri).fsPath, "..", "..", "..").normalize();

src/pom/pomCodeActionProvider.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ export class PomCodeActionProvider implements CodeActionProvider<CodeAction> {
1414

1515
provideCodeActions(document: TextDocument, range: Range | Selection, context: CodeActionContext, token: CancellationToken): ProviderResult<(Command | CodeAction)[]> {
1616
if (context?.diagnostics?.length && context.diagnostics[0].source === "Java") {
17-
return this.collectCodeActionsForNotCoveredExecutions(document, context.diagnostics);
17+
return this.collectCodeActions(document, context.diagnostics);
1818
}
1919

2020
return undefined;
2121
}
2222

23-
private collectCodeActionsForNotCoveredExecutions(document: TextDocument, diagnostics: readonly Diagnostic[]): CodeAction[] {
23+
private collectCodeActions(document: TextDocument, diagnostics: readonly Diagnostic[]): CodeAction[] {
2424
const codeActions: CodeAction[] = [];
2525
for (const diagnostic of diagnostics) {
2626
if (diagnostic.message?.startsWith("Plugin execution not covered by lifecycle configuration")) {
@@ -48,6 +48,14 @@ export class PomCodeActionProvider implements CodeActionProvider<CodeAction> {
4848
action3.edit.insert(document.uri, diagnostic.range.end, indentation + "<?m2e ignore?>");
4949
action3.command = saveAndUpdateConfigCommand;
5050
codeActions.push(action3);
51+
} else if (diagnostic.message?.startsWith("The build file has been changed")) {
52+
const reloadProjectAction = new CodeAction("Reload project", CodeActionKind.QuickFix);
53+
reloadProjectAction.command = {
54+
title: "Reload Project",
55+
command: Commands.CONFIGURATION_UPDATE,
56+
arguments: [document.uri],
57+
};
58+
codeActions.push(reloadProjectAction);
5159
}
5260
}
5361

src/standardLanguageClient.ts

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
import { ExtensionContext, window, workspace, commands, Uri, ProgressLocation, ViewColumn, EventEmitter, extensions, Location, languages, CodeActionKind, TextEditor, CancellationToken, ConfigurationTarget, Range, Position } from "vscode";
3+
import { ExtensionContext, window, workspace, commands, Uri, ProgressLocation, ViewColumn, EventEmitter, extensions, Location, languages, CodeActionKind, TextEditor, CancellationToken, ConfigurationTarget } from "vscode";
44
import { Commands } from "./commands";
55
import { serverStatus, ServerStatusKind } from "./serverStatus";
66
import { prepareExecutable, awaitServerConnection } from "./javaServerStarter";
@@ -36,7 +36,7 @@ import { snippetCompletionProvider } from "./snippetCompletionProvider";
3636
import { JavaInlayHintsProvider } from "./inlayHintsProvider";
3737
import { gradleCodeActionMetadata, GradleCodeActionProvider } from "./gradle/gradleCodeActionProvider";
3838
import { checkLombokDependency } from "./lombokSupport";
39-
import { askForProjects, projectConfigurationUpdate } from "./standardLanguageClientUtils";
39+
import { askForProjects, projectConfigurationUpdate, upgradeGradle } from "./standardLanguageClientUtils";
4040

4141
const extensionName = 'Language Support for Java';
4242
const GRADLE_CHECKSUM = "gradle/checksum/prompt";
@@ -559,7 +559,7 @@ export class StandardLanguageClient {
559559

560560
languages.registerCodeActionsProvider({
561561
scheme: "file",
562-
pattern: "**/gradle/wrapper/gradle-wrapper.properties"
562+
pattern: "**/{gradle/wrapper/gradle-wrapper.properties,build.gradle,build.gradle.kts,settings.gradle,settings.gradle.kts}"
563563
}, new GradleCodeActionProvider(context), gradleCodeActionMetadata);
564564

565565
if (languages.registerInlayHintsProvider) {
@@ -674,31 +674,3 @@ export function showNoLocationFound(message: string): void {
674674
message
675675
);
676676
}
677-
678-
export async function upgradeGradle(projectUri: string, version?: string): Promise<void> {
679-
const useWrapper = workspace.getConfiguration().get<boolean>("java.import.gradle.wrapper.enabled");
680-
if (!useWrapper) {
681-
await workspace.getConfiguration().update("java.import.gradle.wrapper.enabled", true, ConfigurationTarget.Workspace);
682-
}
683-
const result = await window.withProgress({
684-
location: ProgressLocation.Notification,
685-
title: "Upgrading Gradle wrapper...",
686-
cancellable: true,
687-
}, (_progress, token) => {
688-
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, "java.project.upgradeGradle", projectUri, version, token);
689-
});
690-
if (result) {
691-
const propertiesFile = path.join(Uri.parse(projectUri).fsPath, "gradle", "wrapper", "gradle-wrapper.properties");
692-
if (fse.pathExists(propertiesFile)) {
693-
const content = await fse.readFile(propertiesFile);
694-
const offset = content.toString().indexOf("distributionUrl");
695-
if (offset >= 0) {
696-
const document = await workspace.openTextDocument(propertiesFile);
697-
const position = document.positionAt(offset);
698-
const distributionUrlRange = document.getWordRangeAtPosition(position);
699-
window.showTextDocument(document, {selection: new Range(distributionUrlRange.start, new Position(distributionUrlRange.start.line + 1, 0))});
700-
}
701-
}
702-
commands.executeCommand(Commands.IMPORT_PROJECTS_CMD);
703-
}
704-
}

src/standardLanguageClientUtils.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use strict';
22

3-
import { commands, QuickPickItem, Uri, window } from "vscode";
3+
import { commands, ConfigurationTarget, Position, ProgressLocation, QuickPickItem, Range, Uri, window, workspace } from "vscode";
44
import * as path from "path";
5+
import * as fse from "fs-extra";
56
import { TextDocumentIdentifier } from "vscode-languageclient";
67
import { LanguageClient } from "vscode-languageclient/node";
78
import { buildFilePatterns } from "./plugin";
@@ -120,3 +121,31 @@ async function generateProjectPicks(activeFileUri: Uri | undefined): Promise<Qui
120121

121122
return projectPicks;
122123
}
124+
125+
export async function upgradeGradle(projectUri: string, version?: string): Promise<void> {
126+
const useWrapper = workspace.getConfiguration().get<boolean>("java.import.gradle.wrapper.enabled");
127+
if (!useWrapper) {
128+
await workspace.getConfiguration().update("java.import.gradle.wrapper.enabled", true, ConfigurationTarget.Workspace);
129+
}
130+
const result = await window.withProgress({
131+
location: ProgressLocation.Notification,
132+
title: "Upgrading Gradle wrapper...",
133+
cancellable: true,
134+
}, (_progress, token) => {
135+
return commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, "java.project.upgradeGradle", projectUri, version, token);
136+
});
137+
if (result) {
138+
const propertiesFile = path.join(Uri.parse(projectUri).fsPath, "gradle", "wrapper", "gradle-wrapper.properties");
139+
if (fse.pathExists(propertiesFile)) {
140+
const content = await fse.readFile(propertiesFile);
141+
const offset = content.toString().indexOf("distributionUrl");
142+
if (offset >= 0) {
143+
const document = await workspace.openTextDocument(propertiesFile);
144+
const position = document.positionAt(offset);
145+
const distributionUrlRange = document.getWordRangeAtPosition(position);
146+
window.showTextDocument(document, {selection: new Range(distributionUrlRange.start, new Position(distributionUrlRange.start.line + 1, 0))});
147+
}
148+
}
149+
commands.executeCommand(Commands.IMPORT_PROJECTS_CMD);
150+
}
151+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use strict';
2+
3+
import * as assert from 'assert';
4+
import * as path from 'path';
5+
import { CodeAction, CodeActionContext, CodeActionKind, CodeActionTriggerKind, DiagnosticSeverity, ExtensionContext, Position, Range, Uri, window } from "vscode";
6+
import { Commands } from '../../src/commands';
7+
import { GradleCodeActionProvider } from '../../src/gradle/gradleCodeActionProvider';
8+
import { PomCodeActionProvider } from "../../src/pom/pomCodeActionProvider";
9+
10+
// tslint:disable: only-arrow-functions
11+
const mavenProjectFsPath: string = path.join(__dirname, '..', '..', '..', 'test', 'resources', 'projects', 'maven', 'salut');
12+
const gradleProjectFsPath: string = path.join(__dirname, '..', '..', '..', 'test', 'resources', 'projects', 'gradle', 'simple-gradle');
13+
14+
suite('Code Action Provider Test', () => {
15+
16+
test('Provide reload project action on demand for pom file', async function () {
17+
const contextMock = {
18+
subscriptions: []
19+
};
20+
const provider = new PomCodeActionProvider(contextMock as ExtensionContext);
21+
22+
const codeActionContext: CodeActionContext = {
23+
triggerKind: CodeActionTriggerKind.Invoke,
24+
diagnostics: [{
25+
range: new Range(new Position(0, 0), new Position(0, 0)),
26+
message: 'The build file has been changed and may need reload to make it effective.',
27+
severity: DiagnosticSeverity.Information,
28+
source: 'Java'
29+
}],
30+
only: CodeActionKind.QuickFix
31+
};
32+
const editor = await window.showTextDocument(Uri.file(path.join(mavenProjectFsPath, 'pom.xml')));
33+
const codeActions = provider.provideCodeActions(editor.document, null, codeActionContext, null) as CodeAction[];
34+
assert.equal(codeActions.length, 1);
35+
assert.equal(codeActions[0].command.command, Commands.CONFIGURATION_UPDATE);
36+
});
37+
38+
test('Provide reload project action on demand for gradle file', async function () {
39+
const contextMock = {
40+
subscriptions: []
41+
};
42+
const provider = new GradleCodeActionProvider(contextMock as ExtensionContext);
43+
44+
const codeActionContext: CodeActionContext = {
45+
triggerKind: CodeActionTriggerKind.Invoke,
46+
diagnostics: [{
47+
range: new Range(new Position(0, 0), new Position(0, 0)),
48+
message: 'The build file has been changed and may need reload to make it effective.',
49+
severity: DiagnosticSeverity.Information,
50+
source: 'Java'
51+
}],
52+
only: CodeActionKind.QuickFix
53+
};
54+
const editor = await window.showTextDocument(Uri.file(path.join(gradleProjectFsPath, 'build.gradle')));
55+
const codeActions = (await provider.provideCodeActions(editor.document, null, codeActionContext, null)) as CodeAction[];
56+
assert.equal(codeActions.length, 1);
57+
assert.equal(codeActions[0].command.command, Commands.CONFIGURATION_UPDATE);
58+
});
59+
60+
});

0 commit comments

Comments
 (0)