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

Add plugin support #757

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -53,6 +53,12 @@ You can turn on format-on-save on a per-language basis by scoping the setting:

If you have both `"prettier.tslintIntegration"` and `"prettier.eslintIntegration"` enabled in your Visual Studio Code settings, then TSLint will be used to lint your TypeScript code. If you would rather use ESLint, disable the TSLint integration by setting `"prettier.tslintIntegration"` to `false`.

### Prettier Plugins

Prettier plugins are supported when using a custom Prettier installation local or global. The plugins must be installed to the corresponding installation.

Eg. if you have installed Prettier locally to your project with `npm install --save-dev prettier` you must install the plugins like it too `npm install --save-dev @prettier/plugin-php`.

## Settings

### Prettier's Settings
Expand Down
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions package.json
Expand Up @@ -33,6 +33,14 @@
"icon": "icon.png",
"main": "./out/src/extension",
"contributes": {
"commands": [
{
"title": "Show Output Channel",
"category": "Prettier",
"command": "prettier.open-output"
}

],
"configuration": {
"type": "object",
"title": "Prettier - Code formatter configuration",
Expand Down Expand Up @@ -250,6 +258,7 @@
"prettier-stylelint": "^0.4.2",
"prettier-tslint": "^0.4.2",
"read-pkg-up": "^4.0.0",
"requireg": "^0.2.1",
"resolve": "^1.10.0",
"typescript": "^2.9.2"
}
Expand Down
59 changes: 50 additions & 9 deletions src/PrettierEditProvider.ts
Expand Up @@ -6,10 +6,16 @@ import {
FormattingOptions,
CancellationToken,
TextEdit,
window,
} from 'vscode';

import { safeExecution, addToOutput, setUsedModule } from './errorHandler';
import { getParsersFromLanguageId, getConfig } from './utils';
import {
getParsersFromLanguageId,
getConfig,
supportsLanguage,
requireGlobalPrettier,
} from './utils';
import { requireLocalPkg } from './requirePkg';

import {
Expand Down Expand Up @@ -82,6 +88,33 @@ function mergeConfig(
)
: Object.assign(vscodeConfig, prettierConfig, additionalConfig);
}

function getPrettierForFile(
fileName: string
): { prettierInstance: Prettier; type: 'local' | 'global' | 'bundled' } {
// First try to use the local prettier for this file
const local = requireLocalPkg<Prettier>(fileName, 'prettier');
if (local) {
addToOutput('Formatting with local prettier version ' + local.version);
return { type: 'local', prettierInstance: local };
}

// Fallback to global if no local is found
const global = requireGlobalPrettier();
if (global) {
addToOutput(
'Formatting with global prettier version ' + global.version
);
return { type: 'global', prettierInstance: global };
}

// Finally use the bundled one if all else fail
addToOutput(
'Formatting with bundled prettier version ' + bundledPrettier.version
);
return { type: 'bundled', prettierInstance: bundledPrettier };
}

/**
* Format the given text with user's configuration.
* @param text Text to format
Expand All @@ -94,7 +127,6 @@ async function format(
customOptions: Partial<PrettierConfig>
): Promise<string> {
const vscodeConfig: PrettierVSCodeConfig = getConfig(uri);
const localPrettier = requireLocalPkg(fileName, 'prettier') as Prettier;

// This has to stay, as it allows to skip in sub workspaceFolders. Sadly noop.
// wf1 (with "lang") -> glob: "wf1/**"
Expand All @@ -103,9 +135,18 @@ async function format(
return text;
}

const { prettierInstance, type } = getPrettierForFile(fileName);

if (!supportsLanguage(languageId, prettierInstance)) {
window.showErrorMessage(
`Prettier does not support "${languageId}". Maybe a plugin is missing from the workspace?`
);
return text;
}

const dynamicParsers = getParsersFromLanguageId(
languageId,
localPrettier,
prettierInstance,
isUntitled ? undefined : fileName
);
let useBundled = false;
Expand Down Expand Up @@ -177,7 +218,7 @@ async function format(
() => {
const prettierTslint = require('prettier-tslint')
.format as PrettierTslintFormat;
setUsedModule('prettier-tslint', 'Unknown', true);
setUsedModule('prettier-tslint', 'Unknown', 'bundled');

return prettierTslint({
text,
Expand All @@ -194,7 +235,7 @@ async function format(
return safeExecution(
() => {
const prettierEslint = require('prettier-eslint') as PrettierEslintFormat;
setUsedModule('prettier-eslint', 'Unknown', true);
setUsedModule('prettier-eslint', 'Unknown', 'bundled');

return prettierEslint({
text,
Expand Down Expand Up @@ -225,15 +266,15 @@ async function format(
() => {
const warningMessage =
`prettier@${
localPrettier.version
prettierInstance.version
} doesn't support ${languageId}. ` +
`Falling back to bundled prettier@${
bundledPrettier.version
}.`;

addToOutput(warningMessage);

setUsedModule('prettier', bundledPrettier.version, true);
setUsedModule('prettier', bundledPrettier.version, 'bundled');

return bundledPrettier.format(text, prettierOptions);
},
Expand All @@ -242,10 +283,10 @@ async function format(
);
}

setUsedModule('prettier', localPrettier.version, false);
setUsedModule('prettier', prettierInstance.version, type);

return safeExecution(
() => localPrettier.format(text, prettierOptions),
() => prettierInstance.format(text, prettierOptions),
text,
fileName
);
Expand Down
13 changes: 5 additions & 8 deletions src/errorHandler.ts
@@ -1,7 +1,6 @@
import {
Disposable,
StatusBarItem,
OutputChannel,
StatusBarAlignment,
TextEditor,
commands,
Expand All @@ -13,7 +12,7 @@ import { allEnabledLanguages, getConfig } from './utils';
import { PrettierVSCodeConfig } from './types';

let statusBarItem: StatusBarItem;
let outputChannel: OutputChannel;
const outputChannel = window.createOutputChannel('Prettier');
let prettierInformation: string;

function toggleStatusBarItem(editor: TextEditor | undefined): void {
Expand Down Expand Up @@ -71,14 +70,14 @@ function updateStatusBar(message: string): void {
*
* @param module the module used
* @param version the version of the module
* @param bundled is it bundled with the extension or not
* @param type is it local, global or bundled
*/
export function setUsedModule(
module: string,
version: string,
bundled: boolean
type: 'local' | 'global' | 'bundled'
) {
prettierInformation = `${module}@${version}${bundled ? ' (bundled)' : ''}`;
prettierInformation = `${module}@${version} (${type})`;
}

/**
Expand Down Expand Up @@ -147,7 +146,7 @@ export function safeExecution(

return returnValue;
} catch (err) {
addToOutput(addFilePath(err.message, fileName));
addToOutput(addFilePath(err.message || String(err), fileName));
updateStatusBar('Prettier: $(x)');

return defaultText;
Expand All @@ -168,8 +167,6 @@ export function setupErrorHandler(): Disposable {
toggleStatusBarItem(window.activeTextEditor);

// Setup the outputChannel
outputChannel = window.createOutputChannel('Prettier');

return commands.registerCommand('prettier.open-output', () => {
outputChannel.show();
});
Expand Down
6 changes: 3 additions & 3 deletions src/requirePkg.ts
Expand Up @@ -36,19 +36,19 @@ function findPkg(fspath: string, pkgName: string): string | undefined {
* @param {string} pkgName package's name to require
* @returns module
*/
function requireLocalPkg(fspath: string, pkgName: string): any {
function requireLocalPkg<T>(fspath: string, pkgName: string): T | undefined {
let modulePath;
addToOutput('Looking local prettier for ' + fspath);
try {
modulePath = findPkg(fspath, pkgName);
if (modulePath !== void 0) {
addToOutput('Found local prettier ' + modulePath);
return require(modulePath);
}
} catch (e) {
addToOutput(
`Failed to load ${pkgName} from ${modulePath}. Using bundled.`
);
}

return require(pkgName);
}
export { requireLocalPkg };