Skip to content

Commit b0faaef

Browse files
authored
fix: Validate input & change pre-fill value (#366)
1 parent 13c56cf commit b0faaef

File tree

3 files changed

+75
-26
lines changed

3 files changed

+75
-26
lines changed

src/explorerCommands/new.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import * as fse from "fs-extra";
55
import * as path from "path";
66
import { QuickPickItem, Uri, window, workspace, WorkspaceEdit } from "vscode";
77
import { NodeKind } from "../java/nodeData";
8-
import { isJavaIdentifier, isKeyword } from "../utility";
98
import { DataNode } from "../views/dataNode";
9+
import { checkJavaQualifiedName } from "./utils";
1010

1111
export async function newJavaClass(node: DataNode): Promise<void> {
1212
const packageFsPath: string = await getPackageFsPath(node);
@@ -138,24 +138,6 @@ function getNewPackagePath(packageRootPath: string, packageName: string): string
138138
return path.join(packageRootPath, ...packageName.split("."));
139139
}
140140

141-
function checkJavaQualifiedName(value: string): string {
142-
if (!value || !value.trim()) {
143-
return "Input cannot be empty.";
144-
}
145-
146-
for (const part of value.split(".")) {
147-
if (isKeyword(part)) {
148-
return `Keyword '${part}' cannot be used.`;
149-
}
150-
151-
if (!isJavaIdentifier(part)) {
152-
return `Invalid Java qualified name.`;
153-
}
154-
}
155-
156-
return "";
157-
}
158-
159141
interface ISourceRootPickItem extends QuickPickItem {
160142
fsPath: string;
161143
}

src/explorerCommands/rename.ts

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
import * as fse from "fs-extra";
45
import * as path from "path";
56
import { Uri, window, workspace, WorkspaceEdit } from "vscode";
7+
import { NodeKind } from "../java/nodeData";
68
import { DataNode } from "../views/dataNode";
79
import { ExplorerNode } from "../views/explorerNode";
8-
import { isMutable } from "./utils";
10+
import { checkJavaQualifiedName, isMutable } from "./utils";
911

1012
export async function renameFile(node: DataNode, selectedNode: ExplorerNode): Promise<void> {
1113
// if command not invoked by context menu, use selected node in explorer
@@ -16,29 +18,75 @@ export async function renameFile(node: DataNode, selectedNode: ExplorerNode): Pr
1618
}
1719
}
1820

21+
const oldFsPath = Uri.parse(node.uri).fsPath;
22+
1923
const newName: string | undefined = await window.showInputBox({
2024
placeHolder: "Input new file name",
21-
value: node.name,
25+
value: getPrefillValue(node),
2226
ignoreFocusOut: true,
27+
valueSelection: getValueSelection(node.uri),
28+
validateInput: async (value: string): Promise<string> => {
29+
const checkMessage = CheckQualifiedInputName(value, node.nodeData.kind);
30+
if (checkMessage) {
31+
return checkMessage;
32+
}
33+
34+
const inputFsPath = getRenamedFsPath(oldFsPath, value);
35+
if (await fse.pathExists(inputFsPath)) {
36+
return `File path: ${inputFsPath} already exists.`;
37+
}
38+
39+
return "";
40+
},
2341
});
2442

2543
if (!newName) {
2644
return;
2745
}
2846

29-
const oldFsPath = Uri.parse(node.uri).fsPath;
30-
const renamedFilePath = getRenamedFilePath(oldFsPath, newName);
31-
47+
const newFsPath = getRenamedFsPath(oldFsPath, newName);
3248
const workspaceEdit: WorkspaceEdit = new WorkspaceEdit();
33-
workspaceEdit.renameFile(Uri.file(oldFsPath), Uri.file(renamedFilePath));
49+
workspaceEdit.renameFile(Uri.file(oldFsPath), Uri.file(newFsPath));
3450
workspace.applyEdit(workspaceEdit);
3551
}
3652

37-
function getRenamedFilePath(oldUri: string, newName: string): string {
53+
function getRenamedFsPath(oldUri: string, newName: string): string {
3854
// preserve default file extension if not provided
3955
if (!path.extname(newName)) {
4056
newName += path.extname(oldUri);
4157
}
4258
const dirname = path.dirname(oldUri);
4359
return path.join(dirname, newName);
4460
}
61+
62+
function getPrefillValue(node: DataNode): string {
63+
const nodeKind = node.nodeData.kind;
64+
if (nodeKind === NodeKind.PrimaryType) {
65+
return node.name;
66+
}
67+
return path.basename(node.uri);
68+
}
69+
70+
function getValueSelection(uri: string): [number, number] | undefined {
71+
const pos = path.basename(uri).lastIndexOf(".");
72+
if (pos !== -1) {
73+
return [0, pos];
74+
}
75+
return undefined;
76+
}
77+
78+
function CheckQualifiedInputName(value: string, nodeKind: NodeKind): string {
79+
const javaValidateMessage = checkJavaQualifiedName(value);
80+
81+
if (javaValidateMessage) {
82+
return javaValidateMessage;
83+
}
84+
85+
if (nodeKind === NodeKind.Package || nodeKind === NodeKind.PackageRoot) {
86+
if (value.indexOf(".") !== -1) {
87+
return "Rename is only applicable to innermost package.";
88+
}
89+
}
90+
91+
return "";
92+
}

src/explorerCommands/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
import { isJavaIdentifier, isKeyword } from "../utility";
45
import { DataNode } from "../views/dataNode";
56

67
export function isMutable(node: DataNode): boolean {
@@ -11,3 +12,21 @@ export function isMutable(node: DataNode): boolean {
1112
const contextValue = node.computeContextValue();
1213
return packageExp.test(contextValue) || resourceOrTypeExp.test(contextValue);
1314
}
15+
16+
export function checkJavaQualifiedName(value: string): string {
17+
if (!value || !value.trim()) {
18+
return "Input cannot be empty.";
19+
}
20+
21+
for (const part of value.split(".")) {
22+
if (isKeyword(part)) {
23+
return `Keyword '${part}' cannot be used.`;
24+
}
25+
26+
if (!isJavaIdentifier(part)) {
27+
return `Invalid Java qualified name.`;
28+
}
29+
}
30+
31+
return "";
32+
}

0 commit comments

Comments
 (0)