Skip to content

Commit e29f6df

Browse files
authored
Add APIs to get classpaths and settings (#1212)
Signed-off-by: Sheng Chen <sheche@microsoft.com>
1 parent c00bdac commit e29f6df

File tree

3 files changed

+109
-7
lines changed

3 files changed

+109
-7
lines changed

src/commands.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,16 @@ export namespace Commands {
172172
* Show server task status
173173
*/
174174
export const SHOW_SERVER_TASK_STATUS = 'java.show.server.task.status';
175+
/**
176+
* Get the project settings
177+
*/
178+
export const GET_PROJECT_SETTINGS = 'java.project.getSettings';
179+
/**
180+
* Get the classpaths and modulepaths
181+
*/
182+
export const GET_CLASSPATHS = 'java.project.getClasspaths';
183+
/**
184+
* Check the input file is a test file or not
185+
*/
186+
export const IS_TEST_FILE = 'java.project.isTestFile';
175187
}

src/extension.api.ts

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,80 @@
11
import { getDocumentSymbolsCommand } from './documentSymbols';
22
import { RequirementsData } from './requirements';
33
import { TextDocumentPositionParams } from 'vscode-languageclient';
4-
import { CancellationToken, Command, ProviderResult } from 'vscode';
4+
import { CancellationToken, Command, ProviderResult, Uri, Event } from 'vscode';
55

66
export type provideHoverCommandFn = (params: TextDocumentPositionParams, token: CancellationToken) => ProviderResult<Command[] | undefined>;
77
export type registerHoverCommand = (callback: provideHoverCommandFn) => void;
88

9-
export const ExtensionApiVersion = '0.3';
9+
/**
10+
* Gets the project settings.
11+
* @param uri Uri of the source/class file that needs to be queried.
12+
* @param OptionKeys the settings we want to query, for example: ["org.eclipse.jdt.core.compiler.compliance", "org.eclipse.jdt.core.compiler.source"]
13+
* @returns An object with all the optionKeys.
14+
* @throws Will throw errors if the Uri does not belong to any project.
15+
*/
16+
17+
export type getProjectSettingsCommand = (uri: string, SettingKeys: string[]) => Promise<Object>;
18+
19+
/**
20+
* Gets the classpaths and modulepaths.
21+
* @param uri Uri of the source/class file that needs to be queried.
22+
* @param options Query options.
23+
* @returns ClasspathResult containing both classpaths and modulepaths.
24+
* @throws Will throw errors if the Uri does not belong to any project.
25+
*/
26+
27+
export type getClasspathsCommand = (uri: string, options: ClasspathQueryOptions) => Promise<ClasspathResult>;
28+
export type ClasspathQueryOptions = {
29+
/**
30+
* Determines the scope of the classpath. Valid scopes are "runtime" and "test".
31+
* If the given scope is not supported, "runtime" will be used.
32+
*/
33+
scope: string;
34+
};
35+
36+
export type ClasspathResult = {
37+
/**
38+
* Uri string of the project root path.
39+
*/
40+
projectRoot: string;
41+
/**
42+
* File path array for the classpaths.
43+
*/
44+
classpaths: string[];
45+
/**
46+
* File path array for the modulepaths.
47+
*/
48+
modulepaths: string[];
49+
};
50+
51+
/**
52+
* Checks if the input uri is a test source file or not.
53+
* @param uri Uri of the source file that needs to be queried.
54+
* @returns `true` if the input uri is a test file in its belonging project, otherwise returns false.
55+
* @throws Will throw errors if the Uri does not belong to any project.
56+
*/
57+
export type isTestFileCommand = (uri: string) => Promise<boolean>;
58+
59+
export const ExtensionApiVersion = '0.4';
1060

1161
export interface ExtensionAPI {
12-
readonly apiVersion: string;
62+
readonly apiVersion: string;
1363
readonly javaRequirement: RequirementsData;
1464
readonly status: "Started" | "Error";
1565
readonly registerHoverCommand: registerHoverCommand;
1666
readonly getDocumentSymbols: getDocumentSymbolsCommand;
67+
readonly getProjectSettings: getProjectSettingsCommand;
68+
readonly getClasspaths: getClasspathsCommand;
69+
readonly isTestFile: isTestFileCommand;
70+
/**
71+
* An event which fires on classpath update.
72+
*
73+
* Note:
74+
* 1. This event will only fire for Maven/Gradle projects.
75+
* 2. This event will fire when the project's configuration file (e.g. pom.xml for Maven) get changed,
76+
* but the classpaths might still be the same as before.
77+
* 3. The Uri points to the project root path.
78+
*/
79+
readonly onDidClasspathUpdate: Event<Uri>;
1780
}

src/extension.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as path from 'path';
44
import * as os from 'os';
55
import * as fs from 'fs';
66
import { workspace, extensions, ExtensionContext, window, StatusBarAlignment, commands, ViewColumn, Uri, CancellationToken, TextDocumentContentProvider, languages, IndentAction, ProgressLocation, InputBoxOptions, Selection, Position, EventEmitter, OutputChannel, TextDocument, RelativePattern } from 'vscode';
7-
import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, Position as LSPosition, Location as LSLocation, StreamInfo, ErrorHandler, Message, ErrorAction, CloseAction, DidChangeConfigurationNotification } from 'vscode-languageclient';
7+
import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, Position as LSPosition, Location as LSLocation, StreamInfo, ErrorHandler, Message, ErrorAction, CloseAction, DidChangeConfigurationNotification, Emitter } from 'vscode-languageclient';
88
import { onExtensionChange, collectJavaExtensions } from './plugin';
99
import { prepareExecutable, awaitServerConnection } from './javaServerStarter';
1010
import { getDocumentSymbolsCommand, getDocumentSymbolsProvider } from './documentSymbols';
@@ -14,7 +14,7 @@ import {
1414
StatusNotification, ClassFileContentsRequest, ProjectConfigurationUpdateRequest, MessageType, ActionableNotification, FeatureStatus, CompileWorkspaceRequest, CompileWorkspaceStatus, ProgressReportNotification, ExecuteClientCommandRequest, SendNotificationRequest,
1515
SourceAttachmentRequest, SourceAttachmentResult, SourceAttachmentAttribute
1616
} from './protocol';
17-
import { ExtensionAPI, ExtensionApiVersion } from './extension.api';
17+
import { ExtensionAPI, ExtensionApiVersion, ClasspathQueryOptions, ClasspathResult } from './extension.api';
1818
import * as buildpath from './buildpath';
1919
import * as hoverAction from './hoverAction';
2020
import * as sourceAction from './sourceAction';
@@ -242,6 +242,21 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
242242
const snippetProvider: SnippetCompletionProvider = new SnippetCompletionProvider();
243243
context.subscriptions.push(languages.registerCompletionItemProvider({ scheme: 'file', language: 'java' }, snippetProvider));
244244

245+
const getProjectSettings = async (uri: string, SettingKeys: string[]) => {
246+
return await commands.executeCommand<Object>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_PROJECT_SETTINGS, uri, SettingKeys);
247+
};
248+
249+
const getClasspaths = async (uri: string, options: ClasspathQueryOptions) => {
250+
return await commands.executeCommand<ClasspathResult>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_CLASSPATHS, uri, JSON.stringify(options));
251+
};
252+
253+
const isTestFile = async (uri: string) => {
254+
return await commands.executeCommand<boolean>(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.IS_TEST_FILE, uri);
255+
};
256+
257+
const _onDidClasspathUpdate = new Emitter<Uri>();
258+
const onDidClasspathUpdate = _onDidClasspathUpdate.event;
259+
245260
languageClient.onReady().then(() => {
246261
languageClient.onNotification(StatusNotification.type, (report) => {
247262
switch (report.type) {
@@ -253,7 +268,11 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
253268
javaRequirement: requirements,
254269
status: report.type,
255270
registerHoverCommand,
256-
getDocumentSymbols
271+
getDocumentSymbols,
272+
getProjectSettings,
273+
getClasspaths,
274+
isTestFile,
275+
onDidClasspathUpdate
257276
});
258277
snippetProvider.setActivation(false);
259278
break;
@@ -264,7 +283,11 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
264283
javaRequirement: requirements,
265284
status: report.type,
266285
registerHoverCommand,
267-
getDocumentSymbols
286+
getDocumentSymbols,
287+
getProjectSettings,
288+
getClasspaths,
289+
isTestFile,
290+
onDidClasspathUpdate
268291
});
269292
break;
270293
case 'Starting':
@@ -278,6 +301,10 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
278301
serverTasks.updateServerTask(progress);
279302
});
280303
languageClient.onNotification(ActionableNotification.type, (notification) => {
304+
if (notification.message === "__CLASSPATH_UPDATED__") {
305+
_onDidClasspathUpdate.fire(Uri.parse(notification.data));
306+
return;
307+
}
281308
let show = null;
282309
switch (notification.severity) {
283310
case MessageType.Log:

0 commit comments

Comments
 (0)