Skip to content

Commit e8c3551

Browse files
testforstephenfbricon
authored andcommitted
Add context menu to update source attachment for the binary classfile (#699)
Signed-off-by: Jinbo Wang <jinbwan@microsoft.com>
1 parent c70f219 commit e8c3551

5 files changed

Lines changed: 90 additions & 5 deletions

File tree

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,11 @@
291291
"command": "java.clean.workspace",
292292
"title": "Clean the Java language server workspace",
293293
"category": "Java"
294+
},
295+
{
296+
"command": "java.project.updateSourceAttachment",
297+
"title": "Attach Source",
298+
"category": "Java"
294299
}
295300
],
296301
"keybindings": [
@@ -323,6 +328,11 @@
323328
"when": "editorLangId == java",
324329
"group": "1_javaactions"
325330
},
331+
{
332+
"command": "java.project.updateSourceAttachment",
333+
"when": "editorReadonly && editorLangId == java",
334+
"group": "1_javaactions"
335+
},
326336
{
327337
"command": "java.projectConfiguration.update",
328338
"when": "resourceFilename =~ /(.*\\.gradle)|(pom.xml)$/",
@@ -333,6 +343,10 @@
333343
{
334344
"command": "java.edit.organizeImports",
335345
"when": "!editorReadonly && editorLangId == java"
346+
},
347+
{
348+
"command": "java.project.updateSourceAttachment",
349+
"when": "false"
336350
}
337351
]
338352
}

src/commands.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,12 @@ export namespace Commands {
8686
* Clean the Java language server workspace
8787
*/
8888
export const CLEAN_WORKSPACE = 'java.clean.workspace';
89+
/**
90+
* Update the source attachment for the selected class file
91+
*/
92+
export const UPDATE_SOURCE_ATTACHMENT = 'java.project.updateSourceAttachment';
93+
/**
94+
* Resolve the source attachment information for the selected class file
95+
*/
96+
export const RESOLVE_SOURCE_ATTACHMENT = 'java.project.resolveSourceAttachment';
8997
}

src/extension.ts

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@
33
import * as path from 'path';
44
import * as os from 'os';
55
import * as fs from 'fs';
6-
import { workspace, extensions, ExtensionContext, window, StatusBarAlignment, commands, ViewColumn, Uri, CancellationToken, TextDocumentContentProvider, TextEditor, WorkspaceConfiguration, languages, IndentAction, ProgressLocation, InputBoxOptions, Selection, Position } from 'vscode';
7-
import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, ServerOptions, Position as LSPosition, Location as LSLocation, StreamInfo } from 'vscode-languageclient';
6+
import { workspace, extensions, ExtensionContext, window, StatusBarAlignment, commands, ViewColumn, Uri, CancellationToken, TextDocumentContentProvider, TextEditor, WorkspaceConfiguration, languages, IndentAction, ProgressLocation, InputBoxOptions, Selection, Position, EventEmitter } from 'vscode';
7+
import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClient, LanguageClientOptions, RevealOutputChannelOn, ServerOptions, Position as LSPosition, Location as LSLocation, StreamInfo, VersionedTextDocumentIdentifier } from 'vscode-languageclient';
88
import { collectionJavaExtensions } from './plugin';
99
import { prepareExecutable, awaitServerConnection } from './javaServerStarter';
1010
import * as requirements from './requirements';
1111
import { Commands } from './commands';
12-
import { StatusNotification, ClassFileContentsRequest, ProjectConfigurationUpdateRequest, MessageType, ActionableNotification, FeatureStatus, ActionableMessage, CompileWorkspaceRequest, CompileWorkspaceStatus, ProgressReportNotification, ExecuteClientCommandRequest, SendNotificationRequest } from './protocol';
12+
import { StatusNotification, ClassFileContentsRequest, ProjectConfigurationUpdateRequest, MessageType, ActionableNotification, FeatureStatus, ActionableMessage, CompileWorkspaceRequest, CompileWorkspaceStatus, ProgressReportNotification, ExecuteClientCommandRequest, SendNotificationRequest,
13+
SourceAttachmentRequest, SourceAttachmentResult, SourceAttachmentAttribute } from './protocol';
1314
import { ExtensionAPI } from './extension.api';
1415
import * as net from 'net';
1516

1617
let oldConfig;
1718
let lastStatus;
1819
let languageClient: LanguageClient;
20+
let jdtEventEmitter = new EventEmitter<Uri>();
1921
const cleanWorkspaceFileName = '.cleanWorkspace';
2022

2123
export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
@@ -251,12 +253,55 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
251253
});
252254
});
253255

256+
commands.registerCommand(Commands.UPDATE_SOURCE_ATTACHMENT, async (classFileUri: Uri): Promise<boolean> => {
257+
const resolveRequest: SourceAttachmentRequest = {
258+
classFileUri: classFileUri.toString(),
259+
};
260+
const resolveResult: SourceAttachmentResult = await <SourceAttachmentResult>commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.RESOLVE_SOURCE_ATTACHMENT, JSON.stringify(resolveRequest));
261+
if (resolveResult.errorMessage) {
262+
window.showErrorMessage(resolveResult.errorMessage);
263+
return false;
264+
}
265+
266+
const attributes: SourceAttachmentAttribute = resolveResult.attributes || {};
267+
const defaultPath = attributes.sourceAttachmentPath || attributes.jarPath;
268+
const sourceFileUris: Uri[] = await window.showOpenDialog({
269+
defaultUri: defaultPath ? Uri.file(defaultPath) : null,
270+
openLabel: "Select Source File",
271+
canSelectFiles: true,
272+
canSelectFolders: false,
273+
canSelectMany: false,
274+
filters: {
275+
"Source files": ["jar", "zip"]
276+
},
277+
});
278+
279+
if (sourceFileUris && sourceFileUris.length) {
280+
const updateRequest: SourceAttachmentRequest = {
281+
classFileUri: classFileUri.toString(),
282+
attributes: {
283+
...attributes,
284+
sourceAttachmentPath: sourceFileUris[0].fsPath
285+
},
286+
};
287+
const updateResult: SourceAttachmentResult = await <SourceAttachmentResult>commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.UPDATE_SOURCE_ATTACHMENT, JSON.stringify(updateRequest));
288+
if (updateResult.errorMessage) {
289+
window.showErrorMessage(updateResult.errorMessage);
290+
return false;
291+
}
292+
293+
// Notify jdt content provider to rerender the classfile contents.
294+
jdtEventEmitter.fire(classFileUri);
295+
return true;
296+
}
297+
});
298+
254299
window.onDidChangeActiveTextEditor((editor) => {
255300
toggleItem(editor, item);
256301
});
257302

258303
let provider: TextDocumentContentProvider = <TextDocumentContentProvider>{
259-
onDidChange: null,
304+
onDidChange: jdtEventEmitter.event,
260305
provideTextDocumentContent: (uri: Uri, token: CancellationToken): Thenable<string> => {
261306
return languageClient.sendRequest(ClassFileContentsRequest.type, { uri: uri.toString() }, token).then((v: string): string => {
262307
return v || '';

src/protocol.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,21 @@ export namespace ExecuteClientCommandRequest {
103103

104104
export namespace SendNotificationRequest {
105105
export const type = new RequestType<ExecuteCommandParams, any, void, void>('workspace/notify');
106+
}
107+
108+
export interface SourceAttachmentRequest {
109+
classFileUri: string;
110+
attributes?: SourceAttachmentAttribute;
111+
}
112+
113+
export interface SourceAttachmentResult {
114+
errorMessage?: string;
115+
attributes?: SourceAttachmentAttribute;
116+
}
117+
118+
export interface SourceAttachmentAttribute {
119+
jarPath?: string;
120+
sourceAttachmentPath?: string;
121+
sourceAttachmentEncoding?: string;
122+
canEditEncoding?: boolean;
106123
}

test/extension.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ suite('Java Language Extension', () => {
3737
Commands.COMPILE_WORKSPACE,
3838
Commands.EDIT_ORGANIZE_IMPORTS,
3939
Commands.OPEN_FORMATTER,
40-
Commands.CLEAN_WORKSPACE
40+
Commands.CLEAN_WORKSPACE,
41+
Commands.UPDATE_SOURCE_ATTACHMENT
4142
];
4243
let foundJavaCommands = commands.filter(function(value){
4344
return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.');

0 commit comments

Comments
 (0)