Skip to content

Commit

Permalink
Add Code Action: Generate toString()... (#873)
Browse files Browse the repository at this point in the history
Signed-off-by: Jinbo Wang <jinbwan@microsoft.com>
  • Loading branch information
testforstephen authored and fbricon committed Apr 15, 2019
1 parent a249454 commit 61aa100
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 10 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,17 @@ The following settings are supported:
* `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`.
* `java.foldingRange.enabled`: Enable/disable smart folding range support. If disabled, it will use the default indentation-based folding range provided by VS Code.

*New in 0.43.0:*
* `java.maven.downloadSources`: Enable/disable eager download of Maven source artifacts.
* `java.codeGeneration.useBlocks`: Use blocks in 'if' statements when generating the methods. Defaults to `false`.
* `java.codeGeneration.generateComments`: Generate method comments when generating the methods. Defaults to `false`.
* `java.codeGeneration.toString.template`: The template for generating the toString method. Defaults to `${object.className} [${member.name()}=${member.value}, ${otherMembers}]`.
* `java.codeGeneration.toString.codeStyle`: The code style for generating the toString method. Defaults to `STRING_CONCATENATION`.
* `java.codeGeneration.toString.skipNullValues`: Skip null values when generating the toString method. Defaults to `false`.
* `java.codeGeneration.toString.listArrayContents`: List contents of arrays instead of using native toString(). Defaults to `true`.
* `java.codeGeneration.toString.limitElements`: Limit number of items in arrays/collections/maps to list, if 0 then list all. Defaults to `0`.

Troubleshooting
===============
Expand Down
48 changes: 44 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -296,17 +296,57 @@
"default": false,
"scope": "window"
},
"java.codeGeneration.hashCodeEquals.useBlocks": {
"java.codeGeneration.useBlocks": {
"type": "boolean",
"description": "Use blocks in 'if' statements when generating the hashCode and equals methods.",
"description": "Use blocks in 'if' statements when generating the methods.",
"default": false,
"scope": "window"
},
"java.codeGeneration.hashCodeEquals.generateComments": {
"java.codeGeneration.generateComments": {
"type": "boolean",
"description": "Generate method comments when generating the hashCode and equals methods.",
"description": "Generate method comments when generating the methods.",
"default": false,
"scope": "window"
},
"java.codeGeneration.toString.template": {
"type": "string",
"description": "The template for generating the toString method.",
"default": "${object.className} [${member.name()}=${member.value}, ${otherMembers}]"
},
"java.codeGeneration.toString.codeStyle": {
"type": "string",
"enum": [
"STRING_CONCATENATION",
"STRING_BUILDER",
"STRING_BUILDER_CHAINED",
"STRING_FORMAT"
],
"enumDescriptions": [
"String concatenation",
"StringBuilder/StringBuffer",
"StringBuilder/StringBuffer - chained call",
"String.format/MessageFormat"
],
"description": "The code style for generating the toString method.",
"default": "STRING_CONCATENATION"
},
"java.codeGeneration.toString.skipNullValues": {
"type": "boolean",
"description": "Skip null values when generating the toString method.",
"default": false,
"scope": "window"
},
"java.codeGeneration.toString.listArrayContents": {
"type": "boolean",
"description": "List contents of arrays instead of using native toString().",
"default": true,
"scope": "window"
},
"java.codeGeneration.toString.limitElements": {
"type": "integer",
"description": "Limit number of items in arrays/collections/maps to list, if 0 then list all.",
"default": 0,
"scope": "window"
}
}
},
Expand Down
6 changes: 5 additions & 1 deletion src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export namespace Commands {
/**
* Generate hashCode() and equals().
*/
export const HASHCODE_EQUALS_PROMPT = 'java.action.hashCodeEqualsPrompt';
export const HASHCODE_EQUALS_PROMPT = 'java.action.hashCodeEqualsPrompt';
/**
* Open settings.json
*/
Expand All @@ -122,4 +122,8 @@ export namespace Commands {
* Choose type to import.
*/
export const CHOOSE_IMPORTS = "java.action.organizeImports.chooseImports";
/**
* Generate toString().
*/
export const GENERATE_TOSTRING_PROMPT = 'java.action.generateToStringPrompt';
}
3 changes: 2 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
classFileContentsSupport:true,
overrideMethodsPromptSupport:true,
hashCodeEqualsPromptSupport:true,
advancedOrganizeImportsSupport:true
advancedOrganizeImportsSupport:true,
generateToStringPromptSupport:true
},
triggerFiles: getTriggerFiles()
},
Expand Down
19 changes: 19 additions & 0 deletions src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,23 @@ export interface ImportCandidate {
export interface ImportSelection {
candidates: ImportCandidate[];
range: Range;
}

export interface CheckToStringResponse {
type: string;
fields: VariableField[];
exists: boolean;
}

export namespace CheckToStringStatusRequest {
export const type = new RequestType<CodeActionParams, CheckToStringResponse, void, void>('java/checkToStringStatus');
}

export interface GenerateToStringParams {
context: CodeActionParams;
fields: VariableField[];
}

export namespace GenerateToStringRequest {
export const type = new RequestType<GenerateToStringParams, WorkspaceEdit, void, void>('java/generateToString');
}
46 changes: 45 additions & 1 deletion src/sourceAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { CodeActionParams, LanguageClient } from 'vscode-languageclient';
import { Commands } from './commands';
import { applyWorkspaceEdit } from './extension';
import { ListOverridableMethodsRequest, AddOverridableMethodsRequest, CheckHashCodeEqualsStatusRequest, GenerateHashCodeEqualsRequest,
OrganizeImportsRequest, ImportCandidate, ImportSelection } from './protocol';
OrganizeImportsRequest, ImportCandidate, ImportSelection, GenerateToStringRequest, CheckToStringStatusRequest, VariableField } from './protocol';

export function registerCommands(languageClient: LanguageClient, context: ExtensionContext) {
registerOverrideMethodsCommand(languageClient, context);
registerHashCodeEqualsCommand(languageClient, context);
registerOrganizeImportsCommand(languageClient, context);
registerChooseImportCommand(context);
registerGenerateToStringCommand(languageClient, context);
}

function registerOverrideMethodsCommand(languageClient: LanguageClient, context: ExtensionContext): void {
Expand Down Expand Up @@ -158,3 +159,46 @@ function registerChooseImportCommand(context: ExtensionContext): void {
return chosen;
}));
}

function registerGenerateToStringCommand(languageClient: LanguageClient, context: ExtensionContext): void {
context.subscriptions.push(commands.registerCommand(Commands.GENERATE_TOSTRING_PROMPT, async (params: CodeActionParams) => {
const result = await languageClient.sendRequest(CheckToStringStatusRequest.type, params);
if (!result) {
return;
}

if (result.exists) {
const ans = await window.showInformationMessage(`Method 'toString()' already exists in the Class '${result.type}'. `
+ 'Do you want to replace the implementation?', 'Replace', 'Cancel');
if (ans !== 'Replace') {
return;
}
}

let fields: VariableField[] = [];
if (result.fields && result.fields.length) {
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 toString() method.'
});
if (!selectedFields) {
return;
}

fields = selectedFields.map((item) => item.originalField);
}

const workspaceEdit = await languageClient.sendRequest(GenerateToStringRequest.type, {
context: params,
fields,
});
applyWorkspaceEdit(workspaceEdit, languageClient);
}));
}
3 changes: 2 additions & 1 deletion test/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ suite('Java Language Extension', () => {
Commands.HASHCODE_EQUALS_PROMPT,
Commands.OPEN_JSON_SETTINGS,
Commands.ORGANIZE_IMPORTS,
Commands.CHOOSE_IMPORTS
Commands.CHOOSE_IMPORTS,
Commands.GENERATE_TOSTRING_PROMPT
];
let foundJavaCommands = commands.filter(function(value){
return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.');
Expand Down

0 comments on commit 61aa100

Please sign in to comment.