Skip to content

Commit

Permalink
Enable generate hashCode and equals source action (#814)
Browse files Browse the repository at this point in the history
Signed-off-by: Jinbo Wang <[email protected]>
  • Loading branch information
testforstephen authored and fbricon committed Mar 11, 2019
1 parent ca29cb2 commit d8cc49d
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 3 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ The following settings are supported:
* `java.completion.guessMethodArguments` : When set to true, method arguments are guessed when a method is selected from as list of code assist proposals.
* `java.completion.enabled` : Enable/disable code completion support.
* `java.configuration.checkProjectSettingsExclusions`: Checks if the extension-generated project settings files (`.project`, `.classpath`, `.factorypath`, `.settings/`) should be excluded from the file explorer. Defaults to `true`.

* `java.codeGeneration.hashCodeEquals.useJava7Objects`: Use Objects.hash and Objects.equals when generating the hashCode and equals methods. This setting only applies to Java 7 and higher. Defaults to `false`.
* `java.codeGeneration.hashCodeEquals.useInstanceof`: Use 'instanceof' to compare types when generating the hashCode and equals methods. Defaults to `false`.
* `java.codeGeneration.hashCodeEquals.useBlocks`: Use blocks in 'if' statements when generating the hashCode and equals methods. Defaults to `false`.
* `java.codeGeneration.hashCodeEquals.generateComments`: Generate method comments when generating the hashCode and equals methods. Defaults to `false`.

Troubleshooting
===============
Expand Down
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,30 @@
"description": "Enable/disable automatic block formatting when typing `;`, `<enter>` or `}`",
"default": true,
"scope": "window"
},
"java.codeGeneration.hashCodeEquals.useJava7Objects": {
"type": "boolean",
"description": "Use Objects.hash and Objects.equals when generating the hashCode and equals methods. This setting only applies to Java 7 and higher.",
"default": false,
"scope": "window"
},
"java.codeGeneration.hashCodeEquals.useInstanceof": {
"type": "boolean",
"description": "Use 'instanceof' to compare types when generating the hashCode and equals methods.",
"default": false,
"scope": "window"
},
"java.codeGeneration.hashCodeEquals.useBlocks": {
"type": "boolean",
"description": "Use blocks in 'if' statements when generating the hashCode and equals methods.",
"default": false,
"scope": "window"
},
"java.codeGeneration.hashCodeEquals.generateComments": {
"type": "boolean",
"description": "Generate method comments when generating the hashCode and equals methods.",
"default": false,
"scope": "window"
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,8 @@ export namespace Commands {
* Override or implements the methods from the supertypes.
*/
export const OVERRIDE_METHODS_PROMPT = 'java.action.overrideMethodsPrompt';
/**
* Generate hashCode() and equals().
*/
export const HASHCODE_EQUALS_PROMPT = 'java.action.hashCodeEqualsPrompt';
}
3 changes: 2 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
extendedClientCapabilities:{
progressReportProvider: getJavaConfiguration().get('progressReports.enabled'),
classFileContentsSupport:true,
overrideMethodsPromptSupport:true
overrideMethodsPromptSupport:true,
hashCodeEqualsPromptSupport:true
},
triggerFiles: getTriggerFiles()
},
Expand Down
26 changes: 26 additions & 0 deletions src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,30 @@ export interface AddOverridableMethodParams {

export namespace AddOverridableMethodsRequest {
export const type = new RequestType<AddOverridableMethodParams, WorkspaceEdit, void, void>('java/addOverridableMethods');
}

export interface VariableField {
bindingKey: string;
name: string;
type: string;
}

export interface CheckHashCodeEqualsResponse {
type: string;
fields: VariableField[];
existingMethods: string[];
}

export namespace CheckHashCodeEqualsStatusRequest {
export const type = new RequestType<CodeActionParams, CheckHashCodeEqualsResponse, void, void>('java/checkHashCodeEqualsStatus');
}

export interface GenerateHashCodeEqualsParams {
context: CodeActionParams;
fields: VariableField[];
regenerate: boolean;
}

export namespace GenerateHashCodeEqualsRequest {
export const type = new RequestType<GenerateHashCodeEqualsParams, WorkspaceEdit, void, void>('java/generateHashCodeEquals');
}
50 changes: 49 additions & 1 deletion src/sourceAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import { commands, window } from 'vscode';
import { CodeActionParams, LanguageClient } from 'vscode-languageclient';
import { Commands } from './commands';
import { applyWorkspaceEdit } from './extension';
import { ListOverridableMethodsRequest, AddOverridableMethodsRequest } from './protocol';
import { ListOverridableMethodsRequest, AddOverridableMethodsRequest, CheckHashCodeEqualsStatusRequest, GenerateHashCodeEqualsRequest } from './protocol';

export function registerCommands(languageClient: LanguageClient) {
registerOverrideMethodsCommand(languageClient);
registerHashCodeEqualsCommand(languageClient);
}

function registerOverrideMethodsCommand(languageClient: LanguageClient): void {
commands.registerCommand(Commands.OVERRIDE_METHODS_PROMPT, async (params: CodeActionParams) => {
const result = await languageClient.sendRequest(ListOverridableMethodsRequest.type, params);
if (!result || !result.methods || !result.methods.length) {
Expand Down Expand Up @@ -52,3 +57,46 @@ export function registerCommands(languageClient: LanguageClient) {
applyWorkspaceEdit(workspaceEdit, languageClient);
});
}

function registerHashCodeEqualsCommand(languageClient: LanguageClient): void {
commands.registerCommand(Commands.HASHCODE_EQUALS_PROMPT, async (params: CodeActionParams) => {
const result = await languageClient.sendRequest(CheckHashCodeEqualsStatusRequest.type, params);
if (!result || !result.fields || !result.fields.length) {
window.showErrorMessage(`The operation is not applicable to the type ${result.type}.`);
return;
}

let regenerate = false;
if (result.existingMethods && result.existingMethods.length) {
const ans = await window.showInformationMessage(`Methods ${result.existingMethods.join(' and ')} already ${result.existingMethods.length === 1 ? 'exists' : 'exist'} in the Class '${result.type}'. `
+ 'Do you want to regenerate the implementation?', 'Regenerate', 'Cancel');
if (ans !== 'Regenerate') {
return;
}

regenerate = true;
}

const fieldItems = result.fields.map((field) => {
return {
label: `${field.name}: ${field.type}`,
picked: true,
originalField: field
};
});
const selectedFields = await window.showQuickPick(fieldItems, {
canPickMany: true,
placeHolder: 'Select the fields to include in the hashCode() and equals() methods.'
});
if (!selectedFields.length) {
return;
}

const workspaceEdit = await languageClient.sendRequest(GenerateHashCodeEqualsRequest.type, {
context: params,
fields: selectedFields.map((item) => item.originalField),
regenerate
});
applyWorkspaceEdit(workspaceEdit, languageClient);
});
}
1 change: 1 addition & 0 deletions test/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ suite('Java Language Extension', () => {
Commands.REMOVE_FROM_SOURCEPATH,
Commands.LIST_SOURCEPATHS,
Commands.OVERRIDE_METHODS_PROMPT,
Commands.HASHCODE_EQUALS_PROMPT
];
let foundJavaCommands = commands.filter(function(value){
return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.');
Expand Down

0 comments on commit d8cc49d

Please sign in to comment.