Fix project name validation (#22547)

* Fix project name validation

* Add/update tests

* Address comments

* Fix error
This commit is contained in:
Sakshi Sharma
2023-03-31 08:46:58 -07:00
committed by GitHub
parent 6cc5e9a70d
commit 9d8006562d
11 changed files with 124 additions and 153 deletions

View File

@@ -67,7 +67,7 @@ export const whitespaceFilenameErrorMessage = localize('whitespaceFilenameErrorM
export const invalidFileCharsErrorMessage = localize('invalidFileCharsErrorMessage', "Invalid file characters"); export const invalidFileCharsErrorMessage = localize('invalidFileCharsErrorMessage', "Invalid file characters");
export const reservedWindowsFilenameErrorMessage = localize('reservedWindowsFilenameErrorMessage', "This file name is reserved for use by Windows. Choose another name and try again"); export const reservedWindowsFilenameErrorMessage = localize('reservedWindowsFilenameErrorMessage', "This file name is reserved for use by Windows. Choose another name and try again");
export const reservedValueErrorMessage = localize('reservedValueErrorMessage', "Reserved file name. Choose another name and try again"); export const reservedValueErrorMessage = localize('reservedValueErrorMessage', "Reserved file name. Choose another name and try again");
export const trailingWhitespaceErrorMessage = localize('trailingWhitespaceErrorMessage', "File name cannot end with a whitespace"); export const trailingWhitespaceErrorMessage = localize('trailingWhitespaceErrorMessage', "File name cannot start or end with whitespace");
export const tooLongFilenameErrorMessage = localize('tooLongFilenameErrorMessage', "File name cannot be over 255 characters"); export const tooLongFilenameErrorMessage = localize('tooLongFilenameErrorMessage', "File name cannot be over 255 characters");
//Open Existing Dialog //Open Existing Dialog

View File

@@ -59,7 +59,7 @@ export class DataWorkspaceExtension implements IExtension {
return isValidBasename(name); return isValidBasename(name);
} }
isValidBasenameErrorMessage(name?: string): string { isValidBasenameErrorMessage(name?: string): string | undefined {
return isValidBasenameErrorMessage(name); return isValidBasenameErrorMessage(name);
} }

View File

@@ -5,7 +5,6 @@
import * as constants from './constants'; import * as constants from './constants';
import * as os from 'os'; import * as os from 'os';
import * as path from 'path';
const WINDOWS_INVALID_FILE_CHARS = /[\\/:\*\?"<>\|]/g; const WINDOWS_INVALID_FILE_CHARS = /[\\/:\*\?"<>\|]/g;
const UNIX_INVALID_FILE_CHARS = /[\\/]/g; const UNIX_INVALID_FILE_CHARS = /[\\/]/g;
@@ -49,88 +48,57 @@ export function sanitizeStringForFilename(s: string): string {
/** /**
* Returns true if the string is a valid filename * Returns true if the string is a valid filename
* Logic is copied from src\vs\base\common\extpath.ts * Logic is copied from src\vs\base\common\extpath.ts
* @param name filename to check * @param fileName filename to check (without file path)
*/ */
export function isValidBasename(name?: string): boolean { export function isValidBasename(fileName?: string): boolean {
const invalidFileChars = isWindows ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS; if (isValidBasenameErrorMessage(fileName) !== undefined) {
return false; //Return false depicting filename is invalid
if (!name) { } else {
return false; return true;
} }
if (isWindows && name[name.length - 1] === '.') {
return false; // Windows: file cannot end with a "."
}
let basename = path.parse(name).name;
if (!basename || basename.length === 0 || /^\s+$/.test(basename)) {
return false; // require a name that is not just whitespace
}
invalidFileChars.lastIndex = 0;
if (invalidFileChars.test(basename)) {
return false; // check for certain invalid file characters
}
if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(basename)) {
return false; // check for certain invalid file names
}
if (basename === '.' || basename === '..') {
return false; // check for reserved values
}
if (isWindows && basename.length !== basename.trim().length) {
return false; // Windows: file cannot end with a whitespace
}
if (basename.length > 255) {
return false; // most file systems do not allow files > 255 length
}
return true;
} }
/** /**
* Returns specific error message if file name is invalid * Returns specific error message if file name is invalid otherwise returns undefined
* Logic is copied from src\vs\base\common\extpath.ts * Logic is copied from src\vs\base\common\extpath.ts
* @param name filename to check * @param fileName filename to check (without file path)
*/ */
export function isValidBasenameErrorMessage(name?: string): string { export function isValidBasenameErrorMessage(fileName?: string): string | undefined {
const invalidFileChars = isWindows ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS; const invalidFileChars = isWindows ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS;
if (!name) { if (!fileName) {
return constants.undefinedFilenameErrorMessage; return constants.undefinedFilenameErrorMessage;
} }
if (isWindows && name[name.length - 1] === '.') { if (isWindows && fileName[fileName.length - 1] === '.') {
return constants.filenameEndingIsPeriodErrorMessage; // Windows: file cannot end with a "." return constants.filenameEndingIsPeriodErrorMessage; // Windows: file cannot end with a "."
} }
let basename = path.parse(name).name; if (!fileName || fileName.length === 0 || /^\s+$/.test(fileName)) {
if (!basename || basename.length === 0 || /^\s+$/.test(basename)) {
return constants.whitespaceFilenameErrorMessage; // require a name that is not just whitespace return constants.whitespaceFilenameErrorMessage; // require a name that is not just whitespace
} }
invalidFileChars.lastIndex = 0; invalidFileChars.lastIndex = 0;
if (invalidFileChars.test(basename)) { if (invalidFileChars.test(fileName)) {
return constants.invalidFileCharsErrorMessage; // check for certain invalid file characters return constants.invalidFileCharsErrorMessage; // check for certain invalid file characters
} }
if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(basename)) { if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(fileName)) {
return constants.reservedWindowsFilenameErrorMessage; // check for certain invalid file names return constants.reservedWindowsFilenameErrorMessage; // check for certain invalid file names
} }
if (basename === '.' || basename === '..') { if (fileName === '.' || fileName === '..') {
return constants.reservedValueErrorMessage; // check for reserved values return constants.reservedValueErrorMessage; // check for reserved values
} }
if (isWindows && basename.length !== basename.trim().length) { if (isWindows && fileName.length !== fileName.trim().length) {
return constants.trailingWhitespaceErrorMessage; // Windows: file cannot end with a whitespace return constants.trailingWhitespaceErrorMessage; // Windows: file cannot start or end with a whitespace
} }
if (basename.length > 255) { if (fileName.length > 255) {
return constants.tooLongFilenameErrorMessage; // most file systems do not allow files > 255 length return constants.tooLongFilenameErrorMessage; // most file systems do not allow files > 255 length
} }
return ''; return undefined;
} }

View File

@@ -75,11 +75,11 @@ declare module 'dataworkspace' {
isValidBasename(name: string | null | undefined): boolean; isValidBasename(name: string | null | undefined): boolean;
/** /**
* Returns specific error message if file name is invalid * Returns specific error message if file name is invalid otherwise returns undefined
* Logic is copied from src\vs\base\common\extpath.ts * Logic is copied from src\vs\base\common\extpath.ts
* @param name filename to check * @param name filename to check
*/ */
isValidBasenameErrorMessage(name: string | null | undefined): string; isValidBasenameErrorMessage(name: string | null | undefined): string | undefined;
} }
/** /**

View File

@@ -187,7 +187,7 @@ export class NewProjectDialog extends DialogBase {
this.register(projectNameTextBox.onTextChanged(text => { this.register(projectNameTextBox.onTextChanged(text => {
const errorMessage = isValidBasenameErrorMessage(text); const errorMessage = isValidBasenameErrorMessage(text);
if (errorMessage) { if (errorMessage !== undefined) {
// Set validation error message if project name is invalid // Set validation error message if project name is invalid
return void projectNameTextBox.updateProperty('validationErrorMessage', errorMessage); return void projectNameTextBox.updateProperty('validationErrorMessage', errorMessage);
} else { } else {

View File

@@ -9,7 +9,7 @@ import * as constants from '../common/constants';
import { directoryExist, showInfoMessageWithLearnMoreLink } from '../common/utils'; import { directoryExist, showInfoMessageWithLearnMoreLink } from '../common/utils';
import { defaultProjectSaveLocation } from '../common/projectLocationHelper'; import { defaultProjectSaveLocation } from '../common/projectLocationHelper';
import { WorkspaceService } from '../services/workspaceService'; import { WorkspaceService } from '../services/workspaceService';
import { isValidBasename, isValidBasenameErrorMessage } from '../common/pathUtilsHelper'; import { isValidBasenameErrorMessage } from '../common/pathUtilsHelper';
/** /**
* Create flow for a New Project using only VS Code-native APIs such as QuickPick * Create flow for a New Project using only VS Code-native APIs such as QuickPick
@@ -40,7 +40,7 @@ export async function createNewProjectWithQuickpick(workspaceService: WorkspaceS
{ {
title: constants.EnterProjectName, title: constants.EnterProjectName,
validateInput: (value) => { validateInput: (value) => {
return isValidBasename(value) ? undefined : isValidBasenameErrorMessage(value); return isValidBasenameErrorMessage(value);
}, },
ignoreFocusOut: true ignoreFocusOut: true
}); });

View File

@@ -6,7 +6,6 @@
import * as should from 'should'; import * as should from 'should';
import * as constants from '../../common/constants'; import * as constants from '../../common/constants';
import * as os from 'os'; import * as os from 'os';
import * as path from 'path';
import { isValidBasename, isValidBasenameErrorMessage } from '../../common/pathUtilsHelper'; import { isValidBasename, isValidBasenameErrorMessage } from '../../common/pathUtilsHelper';
const isWindows = os.platform() === 'win32'; const isWindows = os.platform() === 'win32';
@@ -14,21 +13,21 @@ const isWindows = os.platform() === 'win32';
suite('Check for invalid filename tests', function (): void { suite('Check for invalid filename tests', function (): void {
test('Should determine invalid filenames', async () => { test('Should determine invalid filenames', async () => {
// valid filename // valid filename
should(isValidBasename(formatFileName('ValidName.sqlproj'))).equal(true); should(isValidBasename('ValidName')).equal(true);
// invalid for both Windows and non-Windows // invalid for both Windows and non-Windows
let invalidNames: string[] = [ let invalidNames: string[] = [
' .sqlproj', ' ',
' .sqlproj', ' ',
' .sqlproj', ' ',
'..sqlproj', '.',
'...sqlproj', '..',
// most file systems do not allow files > 255 length // most file systems do not allow files > 255 length
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.sqlproj' 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
]; ];
for (let invalidName of invalidNames) { for (let invalidName of invalidNames) {
should(isValidBasename(formatFileName(invalidName))).equal(false); should(isValidBasename(invalidName)).equal(false, `InvalidName that failed:${invalidName}`);
} }
should(isValidBasename(undefined)).equal(false); should(isValidBasename(undefined)).equal(false);
@@ -39,52 +38,55 @@ suite('Check for invalid filename tests', function (): void {
test('Should determine invalid Windows filenames', async () => { test('Should determine invalid Windows filenames', async () => {
let invalidNames: string[] = [ let invalidNames: string[] = [
// invalid characters only for Windows // invalid characters only for Windows
'?.sqlproj', '?',
':.sqlproj', ':',
'*.sqlproj', '*',
'<.sqlproj', '<',
'>.sqlproj', '>',
'|.sqlproj', '|',
'".sqlproj', '"',
// Windows filenames cannot end with a whitespace '/',
'test .sqlproj', '\\',
'test .sqlproj' // Windows filenames cannot start or end with a whitespace
'test ',
'test ',
' test'
]; ];
for (let invalidName of invalidNames) { for (let invalidName of invalidNames) {
should(isValidBasename(formatFileName(invalidName))).equal(isWindows ? false : true); should(isValidBasename(invalidName)).equal(isWindows ? false : true, `InvalidName that failed:${invalidName}`);
} }
}); });
test('Should determine Windows forbidden filenames', async () => { test('Should determine Windows forbidden filenames', async () => {
let invalidNames: string[] = [ let invalidNames: string[] = [
// invalid only for Windows // invalid only for Windows
'CON.sqlproj', 'CON',
'PRN.sqlproj', 'PRN',
'AUX.sqlproj', 'AUX',
'NUL.sqlproj', 'NUL',
'COM1.sqlproj', 'COM1',
'COM2.sqlproj', 'COM2',
'COM3.sqlproj', 'COM3',
'COM4.sqlproj', 'COM4',
'COM5.sqlproj', 'COM5',
'COM6.sqlproj', 'COM6',
'COM7.sqlproj', 'COM7',
'COM8.sqlproj', 'COM8',
'COM9.sqlproj', 'COM9',
'LPT1.sqlproj', 'LPT1',
'LPT2.sqlproj', 'LPT2',
'LPT3.sqlproj', 'LPT3',
'LPT4.sqlproj', 'LPT4',
'LPT5.sqlproj', 'LPT5',
'LPT6.sqlproj', 'LPT6',
'LPT7.sqlproj', 'LPT7',
'LPT8.sqlproj', 'LPT8',
'LPT9.sqlproj', 'LPT9',
]; ];
for (let invalidName of invalidNames) { for (let invalidName of invalidNames) {
should(isValidBasename(formatFileName(invalidName))).equal(isWindows ? false : true); should(isValidBasename(invalidName)).equal(isWindows ? false : true);
} }
}); });
}); });
@@ -92,76 +94,77 @@ suite('Check for invalid filename tests', function (): void {
suite('Check for invalid filename error tests', function (): void { suite('Check for invalid filename error tests', function (): void {
test('Should determine invalid filenames', async () => { test('Should determine invalid filenames', async () => {
// valid filename // valid filename
should(isValidBasenameErrorMessage(formatFileName('ValidName.sqlproj'))).equal(''); should(isValidBasenameErrorMessage('ValidName')).equal(undefined);
// invalid for both Windows and non-Windows // invalid for both Windows and non-Windows
should(isValidBasenameErrorMessage(formatFileName(' .sqlproj'))).equal(constants.whitespaceFilenameErrorMessage); should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(formatFileName(' .sqlproj'))).equal(constants.whitespaceFilenameErrorMessage); should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(formatFileName(' .sqlproj'))).equal(constants.whitespaceFilenameErrorMessage); should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(formatFileName('..sqlproj'))).equal(constants.reservedValueErrorMessage); should(isValidBasenameErrorMessage('.')).equal(constants.filenameEndingIsPeriodErrorMessage);
should(isValidBasenameErrorMessage(formatFileName('...sqlproj'))).equal(constants.reservedValueErrorMessage); should(isValidBasenameErrorMessage('..')).equal(constants.filenameEndingIsPeriodErrorMessage);
should(isValidBasenameErrorMessage(undefined)).equal(constants.undefinedFilenameErrorMessage); should(isValidBasenameErrorMessage(undefined)).equal(constants.undefinedFilenameErrorMessage);
should(isValidBasenameErrorMessage('\\')).equal(isWindows ? constants.whitespaceFilenameErrorMessage : constants.invalidFileCharsErrorMessage); should(isValidBasenameErrorMessage('\\')).equal(constants.invalidFileCharsErrorMessage);
should(isValidBasenameErrorMessage('/')).equal(constants.whitespaceFilenameErrorMessage); should(isValidBasenameErrorMessage('/')).equal(constants.invalidFileCharsErrorMessage);
should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
// most file systems do not allow files > 255 length // most file systems do not allow files > 255 length
should(isValidBasenameErrorMessage(formatFileName('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.sqlproj'))).equal(constants.tooLongFilenameErrorMessage); should(isValidBasenameErrorMessage('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).equal(constants.tooLongFilenameErrorMessage);
}); });
test('Should determine invalid Windows filenames', async () => { test('Should determine invalid Windows filenames', async () => {
let invalidNames: string[] = [ let invalidNames: string[] = [
// invalid characters only for Windows // invalid characters only for Windows
'?.sqlproj', '?',
':.sqlproj', ':',
'*.sqlproj', '*',
'<.sqlproj', '<',
'>.sqlproj', '>',
'|.sqlproj', '|',
'".sqlproj' '"',
'\\',
'/'
]; ];
for (let invalidName of invalidNames) { for (let invalidName of invalidNames) {
should(isValidBasenameErrorMessage(formatFileName(invalidName))).equal(isWindows ? constants.invalidFileCharsErrorMessage : ''); should(isValidBasenameErrorMessage(invalidName)).equal(isWindows ? constants.invalidFileCharsErrorMessage : '');
} }
// Windows filenames cannot end with a whitespace // Windows filenames cannot start or end with a whitespace
should(isValidBasenameErrorMessage(formatFileName('test .sqlproj'))).equal(isWindows ? constants.trailingWhitespaceErrorMessage : ''); should(isValidBasenameErrorMessage('test ')).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
should(isValidBasenameErrorMessage(formatFileName('test .sqlproj'))).equal(isWindows ? constants.trailingWhitespaceErrorMessage : ''); should(isValidBasenameErrorMessage('test ')).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
should(isValidBasenameErrorMessage(' test')).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
}); });
test('Should determine Windows forbidden filenames', async () => { test('Should determine Windows forbidden filenames', async () => {
let invalidNames: string[] = [ let invalidNames: string[] = [
// invalid only for Windows // invalid only for Windows
'CON.sqlproj', 'CON',
'PRN.sqlproj', 'PRN',
'AUX.sqlproj', 'AUX',
'NUL.sqlproj', 'NUL',
'COM1.sqlproj', 'COM1',
'COM2.sqlproj', 'COM2',
'COM3.sqlproj', 'COM3',
'COM4.sqlproj', 'COM4',
'COM5.sqlproj', 'COM5',
'COM6.sqlproj', 'COM6',
'COM7.sqlproj', 'COM7',
'COM8.sqlproj', 'COM8',
'COM9.sqlproj', 'COM9',
'LPT1.sqlproj', 'LPT1',
'LPT2.sqlproj', 'LPT2',
'LPT3.sqlproj', 'LPT3',
'LPT4.sqlproj', 'LPT4',
'LPT5.sqlproj', 'LPT5',
'LPT6.sqlproj', 'LPT6',
'LPT7.sqlproj', 'LPT7',
'LPT8.sqlproj', 'LPT8',
'LPT9.sqlproj', 'LPT9',
]; ];
for (let invalidName of invalidNames) { for (let invalidName of invalidNames) {
should(isValidBasenameErrorMessage(formatFileName(invalidName))).equal(isWindows ? constants.reservedWindowsFilenameErrorMessage : ''); should(isValidBasenameErrorMessage(invalidName)).equal(isWindows ? constants.reservedWindowsFilenameErrorMessage : '', `InvalidName that failed:${invalidName}`);
} }
}); });
}); });
function formatFileName(filename: string): string {
return path.join(os.tmpdir(), filename);
}

View File

@@ -785,7 +785,7 @@ export function isValidBasename(name?: string): boolean {
* Returns specific error message if file name is invalid * Returns specific error message if file name is invalid
* @param name filename to check * @param name filename to check
*/ */
export function isValidBasenameErrorMessage(name?: string): string { export function isValidBasenameErrorMessage(name?: string): string | undefined {
return getDataWorkspaceExtensionApi().isValidBasenameErrorMessage(name); return getDataWorkspaceExtensionApi().isValidBasenameErrorMessage(name);
} }

View File

@@ -677,7 +677,7 @@ export class ProjectsController {
prompt: constants.newObjectNamePrompt(itemType.friendlyName), prompt: constants.newObjectNamePrompt(itemType.friendlyName),
value: `${suggestedName}${counter}`, value: `${suggestedName}${counter}`,
validateInput: (value) => { validateInput: (value) => {
return utils.isValidBasename(value) ? undefined : utils.isValidBasenameErrorMessage(value); return utils.isValidBasenameErrorMessage(value);
}, },
ignoreFocusOut: true, ignoreFocusOut: true,
}); });
@@ -1339,7 +1339,7 @@ export class ProjectsController {
prompt: constants.autorestProjectName, prompt: constants.autorestProjectName,
value: defaultName, value: defaultName,
validateInput: (value) => { validateInput: (value) => {
return utils.isValidBasename(value.trim()) ? undefined : utils.isValidBasenameErrorMessage(value.trim()); return utils.isValidBasenameErrorMessage(value);
} }
}); });

View File

@@ -303,7 +303,7 @@ export class CreateProjectFromDatabaseDialog {
this.projectNameTextBox.onTextChanged(text => { this.projectNameTextBox.onTextChanged(text => {
const errorMessage = isValidBasenameErrorMessage(text); const errorMessage = isValidBasenameErrorMessage(text);
if (errorMessage) { if (errorMessage !== undefined) {
// Set validation error message if project name is invalid // Set validation error message if project name is invalid
void this.projectNameTextBox!.updateProperty('validationErrorMessage', errorMessage); void this.projectNameTextBox!.updateProperty('validationErrorMessage', errorMessage);
} else { } else {

View File

@@ -6,7 +6,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as path from 'path'; import * as path from 'path';
import * as constants from '../common/constants'; import * as constants from '../common/constants';
import { exists, getVscodeMssqlApi, isValidBasename, isValidBasenameErrorMessage, sanitizeStringForFilename } from '../common/utils'; import { exists, getVscodeMssqlApi, isValidBasenameErrorMessage, sanitizeStringForFilename } from '../common/utils';
import { IConnectionInfo } from 'vscode-mssql'; import { IConnectionInfo } from 'vscode-mssql';
import { defaultProjectNameFromDb, defaultProjectSaveLocation } from '../tools/newProjectTool'; import { defaultProjectNameFromDb, defaultProjectSaveLocation } from '../tools/newProjectTool';
import { ImportDataModel } from '../models/api/import'; import { ImportDataModel } from '../models/api/import';
@@ -72,7 +72,7 @@ export async function createNewProjectFromDatabaseWithQuickpick(connectionInfo?:
title: constants.projectNamePlaceholderText, title: constants.projectNamePlaceholderText,
value: defaultProjectNameFromDb(sanitizeStringForFilename(selectedDatabase)), value: defaultProjectNameFromDb(sanitizeStringForFilename(selectedDatabase)),
validateInput: (value) => { validateInput: (value) => {
return isValidBasename(value) ? undefined : isValidBasenameErrorMessage(value); return isValidBasenameErrorMessage(value);
}, },
ignoreFocusOut: true ignoreFocusOut: true
}); });