217 lines
6.1 KiB
TypeScript
217 lines
6.1 KiB
TypeScript
/**
|
|
* Prettier Plugin for C/C++/C#/Java/Protobuf formatting using clang-format WebAssembly
|
|
*
|
|
* This plugin provides support for formatting multiple languages using the clang-format WASM implementation.
|
|
* Supported languages:
|
|
* - C / C++
|
|
* - Objective-C / Objective-C++
|
|
* - C#
|
|
* - Java
|
|
* - Protocol Buffer (Protobuf)
|
|
*
|
|
* It supports various file extensions and common clang-format styles.
|
|
*/
|
|
import type { Plugin, Parser, Printer } from 'prettier';
|
|
|
|
// Import the clang-format WASM module
|
|
import clangFormatInit, { format } from './clang-format-vite.js';
|
|
|
|
const parserName = 'clang-format';
|
|
|
|
// Language configuration
|
|
const languages = [
|
|
{
|
|
name: 'C',
|
|
aliases: ['c'],
|
|
parsers: ['c'],
|
|
extensions: ['.c', '.h'],
|
|
filenames: ['*.c', '*.h'],
|
|
aceMode: 'c_cpp',
|
|
tmScope: 'source.c',
|
|
linguistLanguageId: 50,
|
|
vscodeLanguageIds: ['c']
|
|
},
|
|
{
|
|
name: 'C++',
|
|
aliases: ['cpp', 'cxx', 'cc'],
|
|
parsers: ['cpp'],
|
|
extensions: ['.cpp', '.cxx', '.cc', '.hpp', '.hxx', '.hh', '.C', '.H'],
|
|
filenames: ['*.cpp', '*.cxx', '*.cc', '*.hpp', '*.hxx', '*.hh', '*.C', '*.H'],
|
|
aceMode: 'c_cpp',
|
|
tmScope: 'source.cpp',
|
|
linguistLanguageId: 43,
|
|
vscodeLanguageIds: ['cpp']
|
|
},
|
|
{
|
|
name: 'Objective-C',
|
|
aliases: ['objc', 'objectivec'],
|
|
parsers: ['objective-c'],
|
|
extensions: ['.m'],
|
|
filenames: ['*.m'],
|
|
aceMode: 'objectivec',
|
|
tmScope: 'source.objc',
|
|
linguistLanguageId: 259,
|
|
vscodeLanguageIds: ['objective-c']
|
|
},
|
|
{
|
|
name: 'Objective-C++',
|
|
aliases: ['objcpp', 'objectivecpp'],
|
|
parsers: ['objective-cpp'],
|
|
extensions: ['.mm'],
|
|
filenames: ['*.mm'],
|
|
aceMode: 'objectivec',
|
|
tmScope: 'source.objcpp',
|
|
linguistLanguageId: 260,
|
|
vscodeLanguageIds: ['objective-cpp']
|
|
},
|
|
{
|
|
name: 'C#',
|
|
aliases: ['csharp', 'cs'],
|
|
parsers: ['cs'],
|
|
extensions: ['.cs'],
|
|
filenames: ['*.cs'],
|
|
aceMode: 'csharp',
|
|
tmScope: 'source.cs',
|
|
linguistLanguageId: 42,
|
|
vscodeLanguageIds: ['csharp']
|
|
},
|
|
{
|
|
name: 'Java',
|
|
aliases: ['java'],
|
|
parsers: ['java'],
|
|
extensions: ['.java'],
|
|
filenames: ['*.java'],
|
|
aceMode: 'java',
|
|
tmScope: 'source.java',
|
|
linguistLanguageId: 181,
|
|
vscodeLanguageIds: ['java']
|
|
},
|
|
{
|
|
name: 'Protocol Buffer',
|
|
aliases: ['protobuf', 'proto'],
|
|
parsers: ['proto'],
|
|
extensions: ['.proto'],
|
|
filenames: ['*.proto'],
|
|
aceMode: 'protobuf',
|
|
tmScope: 'source.proto',
|
|
linguistLanguageId: 297,
|
|
vscodeLanguageIds: ['proto']
|
|
}
|
|
];
|
|
|
|
// Parser configuration
|
|
const clangParser: Parser<string> = {
|
|
astFormat: parserName,
|
|
parse: (text: string) => text,
|
|
locStart: () => 0,
|
|
locEnd: (node: string) => node.length,
|
|
};
|
|
|
|
// Initialize clang-format WASM module
|
|
let initPromise: Promise<void> | null = null;
|
|
let isInitialized = false;
|
|
|
|
function initClangFormat(): Promise<void> {
|
|
if (initPromise) {
|
|
return initPromise;
|
|
}
|
|
|
|
initPromise = (async () => {
|
|
if (!isInitialized) {
|
|
await clangFormatInit();
|
|
isInitialized = true;
|
|
}
|
|
})();
|
|
|
|
return initPromise;
|
|
}
|
|
|
|
// Printer configuration
|
|
const clangPrinter: Printer<string> = {
|
|
print: (path, options) => {
|
|
try {
|
|
if (!isInitialized) {
|
|
console.warn('clang-format WASM module not initialized, returning original text');
|
|
return (path as any).getValue ? (path as any).getValue() : path.node;
|
|
}
|
|
|
|
const text = (path as any).getValue ? (path as any).getValue() : path.node;
|
|
const style = getClangStyle(options);
|
|
|
|
// Format using clang-format (synchronous call)
|
|
const formatted = format(text, options.filename, style);
|
|
|
|
return formatted.trim();
|
|
} catch (error) {
|
|
console.warn('clang-format failed:', error);
|
|
// Return original text if formatting fails
|
|
return (path as any).getValue ? (path as any).getValue() : path.node;
|
|
}
|
|
},
|
|
};
|
|
|
|
|
|
// Helper function to determine clang-format style
|
|
function getClangStyle(options: any): string {
|
|
// You can extend this to support more options
|
|
const style = options.clangStyle || 'LLVM';
|
|
|
|
// Support common styles
|
|
const validStyles = ['LLVM', 'Google', 'Chromium', 'Mozilla', 'WebKit', 'Microsoft', 'GNU'];
|
|
if (validStyles.includes(style)) {
|
|
return style;
|
|
}
|
|
|
|
// Default to LLVM style
|
|
return 'LLVM';
|
|
}
|
|
|
|
// Plugin options
|
|
const options = {
|
|
clangStyle: {
|
|
since: '0.0.1',
|
|
category: 'Format' as const,
|
|
type: 'choice' as const,
|
|
default: 'LLVM',
|
|
description: 'The clang-format style to use',
|
|
choices: [
|
|
{ value: 'LLVM', description: 'LLVM coding standards' },
|
|
{ value: 'Google', description: "Google's C++ style guide" },
|
|
{ value: 'Chromium', description: "Chromium's style guide" },
|
|
{ value: 'Mozilla', description: "Mozilla's style guide" },
|
|
{ value: 'WebKit', description: "WebKit's style guide" },
|
|
{ value: 'Microsoft', description: "Microsoft's style guide" },
|
|
{ value: 'GNU', description: 'GNU coding standards' }
|
|
]
|
|
},
|
|
filename: {
|
|
// since: '0.1.0',
|
|
category: 'Config',
|
|
type: 'string',
|
|
default: undefined,
|
|
description: 'Custom filename to use for web_fmt processing (affects language detection)',
|
|
}
|
|
};
|
|
|
|
// Plugin object
|
|
const clangPlugin: Plugin = {
|
|
languages,
|
|
parsers: {
|
|
[parserName]: clangParser,
|
|
},
|
|
printers: {
|
|
[parserName]: clangPrinter,
|
|
},
|
|
...options,
|
|
};
|
|
|
|
// Initialize WASM module when plugin loads
|
|
initClangFormat().catch(error => {
|
|
console.warn('Failed to initialize clang-format WASM module:', error);
|
|
});
|
|
|
|
export default clangPlugin;
|
|
export { languages };
|
|
export const parsers = clangPlugin.parsers;
|
|
export const printers = clangPlugin.printers;
|