UNPKG

prettier-plugin-solidity

Version:

A Prettier Plugin for automatically formatting your Solidity code.

185 lines 7.18 kB
// https://prettier.io/docs/en/plugins.html#parsers import parser from '@solidity-parser/parser'; import coerce from 'semver/functions/coerce.js'; import satisfies from 'semver/functions/satisfies.js'; import { printWarning } from './common/print-warning.js'; const tryHug = (node, operators) => { if (node.type === 'BinaryOperation' && operators.includes(node.operator)) return { type: 'TupleExpression', components: [node], isArray: false }; return node; }; function parse(text, _parsers, options = _parsers) { const compiler = coerce(options.compiler); const parsed = parser.parse(text, { loc: true, range: true, comments: true }); parser.visit(parsed, { PragmaDirective(ctx) { // if the pragma is not for solidity we leave. if (ctx.name !== 'solidity') return; // if the compiler option has not been provided we leave. if (!compiler) return; // we make a check against each pragma directive in the document. if (!satisfies(compiler, ctx.value)) { // @TODO: investigate the best way to warn that would apply to // different editors. printWarning(`The compiler option is set to '${options.compiler}', which does not satisfy 'pragma solidity ${ctx.value}'.`); } }, ModifierDefinition(ctx) { if (!ctx.parameters) { ctx.parameters = []; } }, FunctionDefinition(ctx) { if (!ctx.isConstructor) { ctx.modifiers.forEach((modifier) => { var _a; if (((_a = modifier.arguments) === null || _a === void 0 ? void 0 : _a.length) === 0) { modifier.arguments = null; } }); } }, ForStatement(ctx) { if (ctx.initExpression) { ctx.initExpression.omitSemicolon = true; } ctx.loopExpression.omitSemicolon = true; }, HexLiteral(ctx) { const value = ctx.value.slice(4, -1); ctx.value = options.singleQuote ? `hex'${value}'` : `hex"${value}"`; }, Conditional(ctx) { // TODO: while the behaviour is not stable, it should be behind the // experimentalTernaries flag. if (options.experimentalTernaries) { // We can remove parentheses only because we are sure that the // `condition` must be a single `bool` value. while (ctx.condition.type === 'TupleExpression' && !ctx.condition.isArray && ctx.condition.components.length === 1 && ctx.condition.components[0].type !== 'Conditional') { [ctx.condition] = ctx.condition.components; } } }, BinaryOperation(ctx) { switch (ctx.operator) { case '+': case '-': ctx.left = tryHug(ctx.left, ['%']); ctx.right = tryHug(ctx.right, ['%']); break; case '*': ctx.left = tryHug(ctx.left, ['/', '%']); break; case '/': ctx.left = tryHug(ctx.left, ['*', '%']); break; case '%': ctx.left = tryHug(ctx.left, ['*', '/', '%']); break; case '**': // If the compiler has not been given as an option using we leave // a**b**c. if (!compiler) break; if (satisfies(compiler, '>=0.8.0')) { // If the compiler is greater than or equal to 0.8.0 then a**b**c // is formatted as a**(b**c). ctx.right = tryHug(ctx.right, ['**']); break; } if (ctx.right.type === 'BinaryOperation' && ctx.right.operator === '**') { // the parser organizes the a**b**c as a**(b**c) so we need to // restructure it. const left = { type: 'BinaryOperation', operator: '**', left: ctx.left, right: ctx.right.left }; ctx.left = { type: 'TupleExpression', components: [left], isArray: false }; ctx.right = ctx.right.right; } break; case '<<': case '>>': ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']); ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**']); break; case '&': ctx.left = tryHug(ctx.left, ['+', '-', '*', '/', '**', '<<', '>>']); ctx.right = tryHug(ctx.right, ['+', '-', '*', '/', '**', '<<', '>>']); break; case '|': ctx.left = tryHug(ctx.left, [ '+', '-', '*', '/', '**', '<<', '>>', '&', '^' ]); ctx.right = tryHug(ctx.right, [ '+', '-', '*', '/', '**', '<<', '>>', '&', '^' ]); break; case '^': ctx.left = tryHug(ctx.left, [ '+', '-', '*', '/', '**', '<<', '>>', '&' ]); ctx.right = tryHug(ctx.right, [ '+', '-', '*', '/', '**', '<<', '>>', '&' ]); break; case '||': ctx.left = tryHug(ctx.left, ['&&']); ctx.right = tryHug(ctx.right, ['&&']); break; case '&&': default: break; } } }); return parsed; } export default parse; //# sourceMappingURL=parser.js.map