diff --git a/src/slang-nodes/AssemblyStatement.ts b/src/slang-nodes/AssemblyStatement.ts index f1e1d8950..6ff06c97c 100644 --- a/src/slang-nodes/AssemblyStatement.ts +++ b/src/slang-nodes/AssemblyStatement.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { SlangNode } from './SlangNode.js'; import { StringLiteral } from './StringLiteral.js'; import { AssemblyFlagsDeclaration } from './AssemblyFlagsDeclaration.js'; @@ -38,11 +37,13 @@ export class AssemblyStatement extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [ - 'assembly', - print('label'), - print('flags'), + const labelDoc = print('label'); + const flagsDoc = print('flags'); + return [ + 'assembly ', + labelDoc ? [labelDoc, ' '] : labelDoc, + flagsDoc ? [flagsDoc, ' '] : flagsDoc, print('body') - ]); + ]; } } diff --git a/src/slang-nodes/ConstructorDefinition.ts b/src/slang-nodes/ConstructorDefinition.ts index 03c921112..11d1a7609 100644 --- a/src/slang-nodes/ConstructorDefinition.ts +++ b/src/slang-nodes/ConstructorDefinition.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printFunctionWithBody } from '../slang-printers/print-function.js'; +import { printFunction } from '../slang-printers/print-function.js'; import { SlangNode } from './SlangNode.js'; import { ParametersDeclaration } from './ParametersDeclaration.js'; import { ConstructorAttributes } from './ConstructorAttributes.js'; @@ -42,6 +42,6 @@ export class ConstructorDefinition extends SlangNode { } print(print: PrintFunction): Doc { - return printFunctionWithBody('constructor', this, print); + return printFunction('constructor', this, print); } } diff --git a/src/slang-nodes/ContractDefinition.ts b/src/slang-nodes/ContractDefinition.ts index d601632a9..d22a249d4 100644 --- a/src/slang-nodes/ContractDefinition.ts +++ b/src/slang-nodes/ContractDefinition.ts @@ -60,9 +60,8 @@ export class ContractDefinition extends SlangNode { print(print: PrintFunction): Doc { return [ + `${this.abstractKeyword ? 'abstract ' : ''}contract `, group([ - this.abstractKeyword ? 'abstract ' : '', - 'contract ', print('name'), print('specifiers'), this.specifiers.items.length > 0 ? '' : line, diff --git a/src/slang-nodes/DecimalNumberExpression.ts b/src/slang-nodes/DecimalNumberExpression.ts index bc8a20628..f24570f08 100644 --- a/src/slang-nodes/DecimalNumberExpression.ts +++ b/src/slang-nodes/DecimalNumberExpression.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { SlangNode } from './SlangNode.js'; import { NumberUnit } from './NumberUnit.js'; @@ -26,6 +25,7 @@ export class DecimalNumberExpression extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [this.literal, print('unit')]); + const unitDoc = print('unit'); + return [this.literal, unitDoc ? [' ', unitDoc] : unitDoc]; } } diff --git a/src/slang-nodes/ErrorParameter.ts b/src/slang-nodes/ErrorParameter.ts index 9e81ec7d1..132d1ad21 100644 --- a/src/slang-nodes/ErrorParameter.ts +++ b/src/slang-nodes/ErrorParameter.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { TypeName } from './TypeName.js'; @@ -35,6 +34,7 @@ export class ErrorParameter extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [print('typeName'), print('name')]); + const nameDoc = print('name'); + return [print('typeName'), nameDoc ? [' ', nameDoc] : nameDoc]; } } diff --git a/src/slang-nodes/EventParameter.ts b/src/slang-nodes/EventParameter.ts index 997cd5dc9..203e113bf 100644 --- a/src/slang-nodes/EventParameter.ts +++ b/src/slang-nodes/EventParameter.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { TypeName } from './TypeName.js'; @@ -38,10 +37,11 @@ export class EventParameter extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [ + const nameDoc = print('name'); + return [ print('typeName'), - this.indexedKeyword, - print('name') - ]); + this.indexedKeyword ? ' indexed' : '', + nameDoc ? [' ', nameDoc] : nameDoc + ]; } } diff --git a/src/slang-nodes/FallbackFunctionDefinition.ts b/src/slang-nodes/FallbackFunctionDefinition.ts index 4b328474b..ac2229d84 100644 --- a/src/slang-nodes/FallbackFunctionDefinition.ts +++ b/src/slang-nodes/FallbackFunctionDefinition.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printFunctionWithBody } from '../slang-printers/print-function.js'; +import { printFunction } from '../slang-printers/print-function.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { ParametersDeclaration } from './ParametersDeclaration.js'; @@ -60,6 +60,6 @@ export class FallbackFunctionDefinition extends SlangNode { } print(print: PrintFunction): Doc { - return printFunctionWithBody('fallback', this, print); + return printFunction('fallback', this, print); } } diff --git a/src/slang-nodes/FunctionDefinition.ts b/src/slang-nodes/FunctionDefinition.ts index 543651fec..8a34efbcb 100644 --- a/src/slang-nodes/FunctionDefinition.ts +++ b/src/slang-nodes/FunctionDefinition.ts @@ -1,6 +1,6 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; import { satisfies } from 'semver'; -import { printFunctionWithBody } from '../slang-printers/print-function.js'; +import { printFunction } from '../slang-printers/print-function.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { FunctionName } from './FunctionName.js'; @@ -76,6 +76,6 @@ export class FunctionDefinition extends SlangNode { } print(print: PrintFunction): Doc { - return printFunctionWithBody(['function ', print('name')], this, print); + return printFunction(['function ', print('name')], this, print); } } diff --git a/src/slang-nodes/HexNumberExpression.ts b/src/slang-nodes/HexNumberExpression.ts index a55f3dc95..d37ef7da4 100644 --- a/src/slang-nodes/HexNumberExpression.ts +++ b/src/slang-nodes/HexNumberExpression.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { SlangNode } from './SlangNode.js'; import { NumberUnit } from './NumberUnit.js'; @@ -26,6 +25,7 @@ export class HexNumberExpression extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [this.literal, print('unit')]); + const unitDoc = print('unit'); + return [this.literal, unitDoc ? [' ', unitDoc] : unitDoc]; } } diff --git a/src/slang-nodes/InterfaceDefinition.ts b/src/slang-nodes/InterfaceDefinition.ts index 9840a900d..3c464c2fa 100644 --- a/src/slang-nodes/InterfaceDefinition.ts +++ b/src/slang-nodes/InterfaceDefinition.ts @@ -43,8 +43,8 @@ export class InterfaceDefinition extends SlangNode { print(print: PrintFunction): Doc { return [ + 'interface ', group([ - 'interface ', print('name'), this.inheritance ? [' ', print('inheritance')] : line, '{' diff --git a/src/slang-nodes/LibraryDefinition.ts b/src/slang-nodes/LibraryDefinition.ts index 06d96c2a8..b52dab322 100644 --- a/src/slang-nodes/LibraryDefinition.ts +++ b/src/slang-nodes/LibraryDefinition.ts @@ -46,7 +46,8 @@ export class LibraryDefinition extends SlangNode { print(print: PrintFunction): Doc { return [ - group(['library ', print('name'), line, '{']), + 'library ', + group([print('name'), line, '{']), print('members'), '}' ]; diff --git a/src/slang-nodes/MappingKey.ts b/src/slang-nodes/MappingKey.ts index dedf547b5..3f170255d 100644 --- a/src/slang-nodes/MappingKey.ts +++ b/src/slang-nodes/MappingKey.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { MappingKeyType } from './MappingKeyType.js'; @@ -28,6 +27,7 @@ export class MappingKey extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [print('keyType'), print('name')]); + const nameDoc = print('name'); + return [print('keyType'), nameDoc ? [' ', nameDoc] : nameDoc]; } } diff --git a/src/slang-nodes/MappingValue.ts b/src/slang-nodes/MappingValue.ts index 0df330500..765615623 100644 --- a/src/slang-nodes/MappingValue.ts +++ b/src/slang-nodes/MappingValue.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { TypeName } from './TypeName.js'; @@ -35,6 +34,7 @@ export class MappingValue extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [print('typeName'), print('name')]); + const nameDoc = print('name'); + return [print('typeName'), nameDoc ? [' ', nameDoc] : nameDoc]; } } diff --git a/src/slang-nodes/ModifierDefinition.ts b/src/slang-nodes/ModifierDefinition.ts index e067c0598..6ecace6f5 100644 --- a/src/slang-nodes/ModifierDefinition.ts +++ b/src/slang-nodes/ModifierDefinition.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printFunctionWithBody } from '../slang-printers/print-function.js'; +import { printFunction } from '../slang-printers/print-function.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { TerminalNode } from './TerminalNode.js'; @@ -78,6 +78,6 @@ export class ModifierDefinition extends SlangNode { } print(print: PrintFunction): Doc { - return printFunctionWithBody(['modifier ', print('name')], this, print); + return printFunction(['modifier ', print('name')], this, print); } } diff --git a/src/slang-nodes/Parameter.ts b/src/slang-nodes/Parameter.ts index fac9c2ef6..5d5ace961 100644 --- a/src/slang-nodes/Parameter.ts +++ b/src/slang-nodes/Parameter.ts @@ -1,6 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; import { doc } from 'prettier'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { TypeName } from './TypeName.js'; @@ -47,12 +46,12 @@ export class Parameter extends SlangNode { } print(print: PrintFunction): Doc { - return group( - joinExisting(' ', [ - print('typeName'), - print('storageLocation'), - print('name') - ]) - ); + const storageLocationDoc = print('storageLocation'); + const nameDoc = print('name'); + return group([ + print('typeName'), + storageLocationDoc ? [' ', storageLocationDoc] : storageLocationDoc, + nameDoc ? [' ', nameDoc] : nameDoc + ]); } } diff --git a/src/slang-nodes/ReceiveFunctionDefinition.ts b/src/slang-nodes/ReceiveFunctionDefinition.ts index 32137b17e..8cb1d0e19 100644 --- a/src/slang-nodes/ReceiveFunctionDefinition.ts +++ b/src/slang-nodes/ReceiveFunctionDefinition.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printFunctionWithBody } from '../slang-printers/print-function.js'; +import { printFunction } from '../slang-printers/print-function.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { ParametersDeclaration } from './ParametersDeclaration.js'; @@ -49,6 +49,6 @@ export class ReceiveFunctionDefinition extends SlangNode { } print(print: PrintFunction): Doc { - return printFunctionWithBody('receive', this, print); + return printFunction('receive', this, print); } } diff --git a/src/slang-nodes/TryStatement.ts b/src/slang-nodes/TryStatement.ts index d9f642a0a..5f05c75d8 100644 --- a/src/slang-nodes/TryStatement.ts +++ b/src/slang-nodes/TryStatement.ts @@ -1,7 +1,6 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; import { doc } from 'prettier'; import { printSeparatedItem } from '../slang-printers/print-separated-item.js'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { Expression } from './Expression.js'; @@ -52,16 +51,18 @@ export class TryStatement extends SlangNode { } print(print: PrintFunction): Doc { + const returnsDoc = print('returns'); return [ 'try', printSeparatedItem(print('expression'), { firstSeparator: line }), - joinExisting(' ', [ - print('returns'), + [ + returnsDoc ? [returnsDoc, ' '] : returnsDoc, print('body'), + ' ', print('catchClauses') - ]) + ] ]; } } diff --git a/src/slang-nodes/TypedTupleMember.ts b/src/slang-nodes/TypedTupleMember.ts index b004f120c..215eb938f 100644 --- a/src/slang-nodes/TypedTupleMember.ts +++ b/src/slang-nodes/TypedTupleMember.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { TypeName } from './TypeName.js'; @@ -42,10 +41,12 @@ export class TypedTupleMember extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [ + const storageLocationDoc = print('storageLocation'); + return [ print('typeName'), - print('storageLocation'), + storageLocationDoc ? [' ', storageLocationDoc] : storageLocationDoc, + ' ', print('name') - ]); + ]; } } diff --git a/src/slang-nodes/UnnamedFunctionDefinition.ts b/src/slang-nodes/UnnamedFunctionDefinition.ts index 047f81efb..2662e7586 100644 --- a/src/slang-nodes/UnnamedFunctionDefinition.ts +++ b/src/slang-nodes/UnnamedFunctionDefinition.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printFunctionWithBody } from '../slang-printers/print-function.js'; +import { printFunction } from '../slang-printers/print-function.js'; import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { ParametersDeclaration } from './ParametersDeclaration.js'; @@ -49,6 +49,6 @@ export class UnnamedFunctionDefinition extends SlangNode { } print(print: PrintFunction): Doc { - return printFunctionWithBody('function', this, print); + return printFunction('function', this, print); } } diff --git a/src/slang-nodes/UntypedTupleMember.ts b/src/slang-nodes/UntypedTupleMember.ts index 3944e182c..6e6c57380 100644 --- a/src/slang-nodes/UntypedTupleMember.ts +++ b/src/slang-nodes/UntypedTupleMember.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { SlangNode } from './SlangNode.js'; import { StorageLocation } from './StorageLocation.js'; import { TerminalNode } from './TerminalNode.js'; @@ -30,6 +29,10 @@ export class UntypedTupleMember extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [print('storageLocation'), print('name')]); + const storageLocationDoc = print('storageLocation'); + return [ + storageLocationDoc ? [storageLocationDoc, ' '] : storageLocationDoc, + print('name') + ]; } } diff --git a/src/slang-nodes/YulVariableDeclarationStatement.ts b/src/slang-nodes/YulVariableDeclarationStatement.ts index 3b30265e8..371351708 100644 --- a/src/slang-nodes/YulVariableDeclarationStatement.ts +++ b/src/slang-nodes/YulVariableDeclarationStatement.ts @@ -1,5 +1,4 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { SlangNode } from './SlangNode.js'; import { YulVariableDeclarationValue } from './YulVariableDeclarationValue.js'; import { YulVariableNames } from './YulVariableNames.js'; @@ -36,6 +35,7 @@ export class YulVariableDeclarationStatement extends SlangNode { } print(print: PrintFunction): Doc { - return joinExisting(' ', [['let', print('variables')], print('value')]); + const valueDoc = print('value'); + return ['let', print('variables'), valueDoc ? [' ', valueDoc] : valueDoc]; } } diff --git a/src/slang-printers/print-comments.ts b/src/slang-printers/print-comments.ts index ce8e5a887..57c8e67ae 100644 --- a/src/slang-printers/print-comments.ts +++ b/src/slang-printers/print-comments.ts @@ -1,12 +1,11 @@ import { doc, util } from 'prettier'; import { printComment } from '../slang-comments/printer.js'; -import { joinExisting } from '../slang-utils/join-existing.js'; import { locEnd } from '../slang-utils/loc.js'; import type { AstPath, Doc, ParserOptions } from 'prettier'; import type { Comment, PrintableNode } from '../slang-nodes/types.d.ts'; -const { hardline, line } = doc.builders; +const { hardline } = doc.builders; function isPrintable(comment: Comment): boolean { return !comment.trailing && !comment.leading && !comment.printed; @@ -21,20 +20,21 @@ export function printComments( if (lastPrintableIndex === -1) { return []; } - return joinExisting( - line, - path.map(({ node: comment }, index) => { - if (!isPrintable(comment)) { - return ''; - } - comment.printed = true; - return [ - printComment(path), - index !== lastPrintableIndex && - util.isNextLineEmpty(options.originalText, locEnd(comment)) - ? hardline - : '' - ]; - }, 'comments') - ); + return path.map(({ node: comment }, index) => { + if (!isPrintable(comment)) { + return ''; + } + comment.printed = true; + return [ + printComment(path), + index !== lastPrintableIndex + ? [ + hardline, + util.isNextLineEmpty(options.originalText, locEnd(comment)) + ? hardline + : '' + ] + : '' + ]; + }, 'comments'); } diff --git a/src/slang-printers/print-function.ts b/src/slang-printers/print-function.ts index 46dd7e254..dc895148a 100644 --- a/src/slang-printers/print-function.ts +++ b/src/slang-printers/print-function.ts @@ -1,6 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; import { doc } from 'prettier'; -import { joinExisting } from '../slang-utils/join-existing.js'; import type { Doc } from 'prettier'; import type { FunctionLike, FunctionWithBody } from '../slang-nodes/types.d.ts'; @@ -13,24 +12,21 @@ export function printFunction( node: FunctionLike, print: PrintFunction ): Doc { - return group([ - functionName, - print('parameters'), - indent( - group([ - joinExisting(line, [print('attributes'), print('returns')]), - (node as FunctionWithBody).body?.kind === NonterminalKind.Block - ? dedent(line) - : '' - ]) - ) - ]); -} - -export function printFunctionWithBody( - functionName: Doc, - node: FunctionLike, - print: PrintFunction -): Doc { - return [printFunction(functionName, node, print), print('body')]; + const returnsDoc = print('returns'); + return [ + group([ + functionName, + print('parameters'), + indent( + group([ + print('attributes'), + returnsDoc ? [line, returnsDoc] : returnsDoc, + (node as FunctionWithBody).body?.kind === NonterminalKind.Block + ? dedent(line) + : '' + ]) + ) + ]), + print('body') + ]; } diff --git a/src/slang-utils/join-existing.ts b/src/slang-utils/join-existing.ts deleted file mode 100644 index 5fd60b7b5..000000000 --- a/src/slang-utils/join-existing.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { doc } from 'prettier'; - -import type { Doc } from 'prettier'; - -const { join } = doc.builders; - -export function joinExisting(sep: Doc, docs: (Doc | undefined)[]): Doc[] { - return join(sep, docs.filter(Boolean) as Doc[]); -}