Repository: microsoft/vscode (TypeScript)
Date: 2021-01-05 18:26:16+00:00
Task type: Bug Fix

Issue:
increment file name does not work with zero prefixed file name when using smart incremental naming
<!-- ⚠️⚠️ Do Not Delete This! bug_report_template ⚠️⚠️ -->
<!-- Please read our Rules of Conduct: https://opensource.microsoft.com/codeofconduct/ -->
<!-- Please search existing issues to avoid creating duplicates. -->
<!-- Also please test using the latest insiders build to make sure your issue has not already been fixed: https://code.visualstudio.com/insiders/ -->

<!-- Use Help > Report Issue to prefill these. -->
Version: 1.52.1
Commit: ea3859d4ba2f3e577a159bc91e3074c5d85c0523
Date: 2020-12-16T16:30:02.420Z
Electron: 9.3.5
Chrome: 83.0.4103.122
Node.js: 12.14.1
V8: 8.3.110.13-electron.0
OS: Darwin x64 20.2.0

Steps to Reproduce:

1. Create a file called `0001004` in the explorer.
2. Copy that file. 
3. Paste that file. 
4. The new file name is `0001004.1`, where it should be `0001005`.


<img width="220" alt="Screenshot 2021-01-05 at 11 08 23" src="https://user-images.githubusercontent.com/552769/103634000-c832a780-4f46-11eb-9967-320c07e0219f.png">


<!-- Launch with `code --disable-extensions` to check. -->
Does this issue occur when all extensions are disabled?: Yes



Issue discussion:
(Experimental duplicate detection)
Thanks for submitting this issue. Please also check if it is already covered by an existing one, like:
- [The extension cannot be used after the update (#113219)](https://www.github.com/microsoft/vscode/issues/113219) <!-- score: 0.485 -->
- ["file copy + rename" scenario explorer bug on Mac OS (#113446)](https://www.github.com/microsoft/vscode/issues/113446) <!-- score: 0.474 -->
<!-- potential_duplicates_comment -->
I think the code is in https://github.com/microsoft/vscode/blob/ebdff39cca7f5ee5e4ddd16e92d7fce2cce5cd93/src/vs/workbench/contrib/files/browser/fileActions.ts#L363-L454. Last time I checked there was also no test case for that. 
Thanks. I acknowledge the issue. And we would welcome a PR that neatly fixes this and adds a test, thus adding help wanted label.
Not a Typescript magician here, otherwise I would have provided a pull request. 😬 
I can submit a PR.  @isidorn looking at the file/folder checks it looks like these two sets should be added.  If they look right, I will send a PR for them.

- File without extension
  - `file => file1`
  - `file1 => file2`
- Version number only, without extension
  - `1` => `2`

@nrayburn-tech makes sense. Make sure to cover with tests and no need to go too fancy! Thanks
@isidorn One other incrementing that I am not sure about.  `0999.txt` becomes `1000.txt`, without the leading 0.  Is this right, or should it maintain the number of leading 0s?
If you have zero leading paddings it usually means the amount of characters
should be maintained. So making 01000 out of 0999 would be wrong IMO. It
should just become 1000. Me two cents.

On Tue, 5 Jan 2021, 18:28 Nicholas Rayburn, <notifications@github.com>
wrote:

> @isidorn <https://github.com/isidorn> One other incrementing that I am
> not sure about. 0999.txt becomes 1000.txt, without the leading 0. Is this
> right, or should it maintain the number of leading 0s?
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/microsoft/vscode/issues/113809#issuecomment-754780505>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAEG6QJUEJG3IXJ4ALSKVY3SYND2PANCNFSM4VUYY2FQ>
> .
>

I agree with @xh3b4sd 

Solution patch:
diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts
--- a/src/vs/workbench/contrib/files/browser/fileActions.ts
+++ b/src/vs/workbench/contrib/files/browser/fileActions.ts
@@ -379,6 +379,32 @@ export function incrementFileName(name: string, isFolder: boolean, incrementalNa
 		return `${name.substr(0, lastIndexOfDot)}.1${name.substr(lastIndexOfDot)}`;
 	}
 
+	// 123 => 124
+	let noNameNoExtensionRegex = RegExp('(\\d+)$');
+	if (!isFolder && lastIndexOfDot === -1 && name.match(noNameNoExtensionRegex)) {
+		return name.replace(noNameNoExtensionRegex, (match, g1?) => {
+			let number = parseInt(g1);
+			return number < maxNumber
+				? String(number + 1).padStart(g1.length, '0')
+				: `${g1}.1`;
+		});
+	}
+
+	// file => file1
+	// file1 => file2
+	let noExtensionRegex = RegExp('(.*)(\d*)$');
+	if (!isFolder && lastIndexOfDot === -1 && name.match(noExtensionRegex)) {
+		return name.replace(noExtensionRegex, (match, g1?, g2?) => {
+			let number = parseInt(g2);
+			if (isNaN(number)) {
+				number = 0;
+			}
+			return number < maxNumber
+				? g1 + String(number + 1).padStart(g2.length, '0')
+				: `${g1}${g2}.1`;
+		});
+	}
+
 	// folder.1=>folder.2
 	if (isFolder && name.match(/(\d+)$/)) {
 		return name.replace(/(\d+)$/, (match, ...groups) => {


Test patch:
diff --git a/src/vs/workbench/contrib/files/test/browser/fileActions.test.ts b/src/vs/workbench/contrib/files/test/browser/fileActions.test.ts
--- a/src/vs/workbench/contrib/files/test/browser/fileActions.test.ts
+++ b/src/vs/workbench/contrib/files/test/browser/fileActions.test.ts
@@ -258,7 +258,7 @@ suite('Files - Increment file name smart', () => {
 		assert.strictEqual(result, '2-test.js');
 	});
 
-	test('Increment file name with prefix version with `-` as separator', function () {
+	test('Increment file name with prefix version with `_` as separator', function () {
 		const name = '1_test.js';
 		const result = incrementFileName(name, false, 'smart');
 		assert.strictEqual(result, '2_test.js');
@@ -270,6 +270,36 @@ suite('Files - Increment file name smart', () => {
 		assert.strictEqual(result, '9007199254740992.test.1.js');
 	});
 
+	test('Increment file name with just version and no extension', function () {
+		const name = '001004';
+		const result = incrementFileName(name, false, 'smart');
+		assert.strictEqual(result, '001005');
+	});
+
+	test('Increment file name with just version and no extension, too big number', function () {
+		const name = '9007199254740992';
+		const result = incrementFileName(name, false, 'smart');
+		assert.strictEqual(result, '9007199254740992.1');
+	});
+
+	test('Increment file name with no extension and no version', function () {
+		const name = 'file';
+		const result = incrementFileName(name, false, 'smart');
+		assert.strictEqual(result, 'file1');
+	});
+
+	test('Increment file name with no extension', function () {
+		const name = 'file1';
+		const result = incrementFileName(name, false, 'smart');
+		assert.strictEqual(result, 'file2');
+	});
+
+	test('Increment file name with no extension, too big number', function () {
+		const name = 'file9007199254740992';
+		const result = incrementFileName(name, false, 'smart');
+		assert.strictEqual(result, 'file9007199254740992.1');
+	});
+
 	test('Increment folder name with prefix version', function () {
 		const name = '1.test';
 		const result = incrementFileName(name, true, 'smart');