Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable multiple extensions path to emmet.extensionPath setting #52

Merged
merged 9 commits into from
Feb 22, 2021
Merged
70 changes: 47 additions & 23 deletions src/emmetHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -949,37 +949,60 @@ function getFormatters(syntax: string, preferences: any) {

/**
* Updates customizations from snippets.json and syntaxProfiles.json files in the directory configured in emmet.extensionsPath setting
* @param emmetExtensionsPathSetting setting passed from emmet.extensionsPath, support multiple path setting
* https://github.com/microsoft/vscode/issues/116741
*/
export async function updateExtensionsPath(emmetExtensionsPath: string | undefined | null, fs: FileService, workspaceFolderPath?: URI, homeDir?: URI): Promise<void> {
if (emmetExtensionsPath) {
emmetExtensionsPath = emmetExtensionsPath.trim();
}
if (!emmetExtensionsPath) {
resetSettingsFromFile();
return Promise.resolve();
export async function updateExtensionsPath(emmetExtensionsPathSetting: string | string[] | undefined | null, fs: FileService, workspaceFolderPath?: URI, homeDir?: URI): Promise<void> {
let emmetExtensionsArray: string[];

if (Array.isArray(emmetExtensionsPathSetting)) {
emmetExtensionsArray = emmetExtensionsPathSetting;
} else {
emmetExtensionsArray = [emmetExtensionsPathSetting];
}

let emmetExtensionsPathUri: URI | undefined;
if (emmetExtensionsPath[0] === '~') {
if (homeDir) {
emmetExtensionsPathUri = joinPath(homeDir, emmetExtensionsPath.substr(1));
let hasValidPath = false;
for (let emmetExtensionsPath of emmetExtensionsArray) {
if (emmetExtensionsPath) {
emmetExtensionsPath = emmetExtensionsPath.trim();
}
} else if (!isAbsolutePath(emmetExtensionsPath)) {
if (workspaceFolderPath) {
emmetExtensionsPathUri = joinPath(workspaceFolderPath, emmetExtensionsPath);
if (!emmetExtensionsPath) {
resetSettingsFromFile();
return Promise.resolve();
}
} else {
emmetExtensionsPathUri = URI.file(emmetExtensionsPath);
}

try {
// the fs.stat call itself could throw, so we wrap this part up into a try-catch
if (!emmetExtensionsPathUri || (await fs.stat(emmetExtensionsPathUri)).type !== FileType.Directory) {
throw new Error();
if (emmetExtensionsPath[0] === '~') {
if (homeDir) {
emmetExtensionsPathUri = joinPath(homeDir, emmetExtensionsPath.substr(1));
}
} else if (!isAbsolutePath(emmetExtensionsPath)) {
if (workspaceFolderPath) {
emmetExtensionsPathUri = joinPath(workspaceFolderPath, emmetExtensionsPath);
}
} else {
emmetExtensionsPathUri = URI.file(emmetExtensionsPath);
}
} catch (e) {

try {
// the fs.stat call itself could throw, so we wrap this part up into a try-catch
if (!emmetExtensionsPathUri || (await fs.stat(emmetExtensionsPathUri)).type !== FileType.Directory) {
throw new Error();
}
} catch (e) {
continue;
}
hasValidPath = true;
break;
}

if (!hasValidPath) {
resetSettingsFromFile();
throw new Error(`The directory ${emmetExtensionsPath} doesn't exist. Update emmet.extensionsPath setting`);
if (Array.isArray(emmetExtensionsPathSetting)) {
throw new Error(localize("Emmet extensionsPath plural directories error", "All of the directories in the array doesn't exist. Update emmet.extensionsPath setting"));
} else {
throw new Error(localize("Emmet extensionsPath single directory error", `The directory ${emmetExtensionsPathSetting} doesn't exist. Update emmet.extensionsPath setting`));
}
}

const snippetsPath = joinPath(emmetExtensionsPathUri, 'snippets.json');
Expand Down Expand Up @@ -1027,7 +1050,7 @@ export async function updateExtensionsPath(emmetExtensionsPath: string | undefin
});
} catch (e) {
resetSettingsFromFile();
throw new Error(`Error while parsing the file ${snippetsPath}`);
throw new Error(localize("Emmet extensionsPath parsing error", `Error while parsing the file ${snippetsPath}`));
}

try {
Expand All @@ -1048,6 +1071,7 @@ function resetSettingsFromFile() {
variablesFromFile = {};
}


/**
* Get the corresponding emmet mode for given vscode language mode
* Eg: jsx for typescriptreact/javascriptreact or pug for jade
Expand Down
27 changes: 26 additions & 1 deletion src/test/emmetHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const fileService: FileService = {
}
}

function updateExtensionsPath(extPath: string): Promise<void> {
function updateExtensionsPath(extPath: string | string[]): Promise<void> {
return updateExtensionsPathHelper(extPath, fileService, URI.file('/home/projects/test'))
}

Expand Down Expand Up @@ -455,6 +455,31 @@ describe('Test custom snippets', () => {
assert.ok(!getExpandOptions('scss').snippets, 'There should be no custom snippets as extensionPath was faulty');
}
});

// https://github.com/microsoft/vscode/issues/116741
it('should use the first valid custom snippets from an array of extensions path', async () => {
const customSnippetKey = 'ch';
await updateExtensionsPath(null);
const expandOptionsWithoutCustomSnippets = getExpandOptions('css');
assert(!expandOptionsWithoutCustomSnippets.snippets);

// Use custom snippets from extensionsPathArray
const extensionsPathArray = ["./this/is/not/valid", extensionsPath]
await updateExtensionsPath(extensionsPathArray);
const expandOptionsWithCustomSnippets = getExpandOptions('css');

assert.strictEqual(Object.keys(expandOptionsWithCustomSnippets.snippets).some(key => key === customSnippetKey), true);
});

it('should throw error when all extensionsPath in the array are invalid', async () => {
const extensionsPathArray = ["./this/is/not/valid", "./this/is/also/not/valid"]
try {
await updateExtensionsPath(extensionsPathArray);
return Promise.reject('There should be an error as no valid path is found in the array');
} catch (e) {
assert.ok(e);
}
});
});

describe('Test emmet preferences', () => {
Expand Down