diff --git a/src/slang-comments/handlers/handle-modifier-invocation-comments.ts b/src/slang-comments/handlers/handle-modifier-invocation-comments.ts index 06e8d749a..d1b5e3187 100644 --- a/src/slang-comments/handlers/handle-modifier-invocation-comments.ts +++ b/src/slang-comments/handlers/handle-modifier-invocation-comments.ts @@ -27,14 +27,12 @@ export default function handleModifierInvocationComments({ if ( precedingNode?.kind === NonterminalKind.IdentifierPath && nextCharacter === '(' && - followingNode?.kind === NonterminalKind.ArgumentsDeclaration && - followingNode.variant.kind === - NonterminalKind.PositionalArgumentsDeclaration + followingNode?.kind === NonterminalKind.PositionalArgumentsDeclaration ) { - if (followingNode.variant.arguments.items.length === 0) { + if (followingNode.arguments.items.length === 0) { addTrailingComment(enclosingNode, comment); } else { - addCollectionFirstComment(followingNode.variant.arguments, comment); + addCollectionFirstComment(followingNode.arguments, comment); } return true; } diff --git a/src/slang-nodes/ArgumentsDeclaration.ts b/src/slang-nodes/ArgumentsDeclaration.ts index 34b5f288a..b896b17ed 100644 --- a/src/slang-nodes/ArgumentsDeclaration.ts +++ b/src/slang-nodes/ArgumentsDeclaration.ts @@ -1,6 +1,6 @@ import * as ast from '@nomicfoundation/slang/ast'; import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { PolymorphicNode } from './PolymorphicNode.js'; +import { SlangNode } from './SlangNode.js'; import { PositionalArgumentsDeclaration } from './PositionalArgumentsDeclaration.js'; import { NamedArgumentsDeclaration } from './NamedArgumentsDeclaration.js'; @@ -21,7 +21,7 @@ function createNonterminalVariant( return exhaustiveCheck; } -export class ArgumentsDeclaration extends PolymorphicNode { +export class ArgumentsDeclaration extends SlangNode { readonly kind = NonterminalKind.ArgumentsDeclaration; variant: PositionalArgumentsDeclaration | NamedArgumentsDeclaration; diff --git a/src/slang-nodes/EmitStatement.ts b/src/slang-nodes/EmitStatement.ts index 81fcc6956..42e7166ec 100644 --- a/src/slang-nodes/EmitStatement.ts +++ b/src/slang-nodes/EmitStatement.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printVariant } from '../slang-printers/print-variant.js'; +import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { IdentifierPath } from './IdentifierPath.js'; import { ArgumentsDeclaration } from './ArgumentsDeclaration.js'; @@ -14,13 +14,15 @@ export class EmitStatement extends SlangNode { event: IdentifierPath; - arguments: ArgumentsDeclaration; + arguments: ArgumentsDeclaration['variant']; constructor(ast: ast.EmitStatement, options: ParserOptions) { super(ast); this.event = new IdentifierPath(ast.event); - this.arguments = new ArgumentsDeclaration(ast.arguments, options); + this.arguments = extractVariant( + new ArgumentsDeclaration(ast.arguments, options) + ); this.updateMetadata(this.event, this.arguments); } @@ -29,7 +31,7 @@ export class EmitStatement extends SlangNode { return [ 'emit ', path.call(print, 'event'), - path.call(printVariant(print), 'arguments'), + path.call(print, 'arguments'), ';' ]; } diff --git a/src/slang-nodes/FunctionCallExpression.ts b/src/slang-nodes/FunctionCallExpression.ts index 2570711ef..fdfa7c0b2 100644 --- a/src/slang-nodes/FunctionCallExpression.ts +++ b/src/slang-nodes/FunctionCallExpression.ts @@ -3,6 +3,7 @@ import { doc } from 'prettier'; import { isLabel } from '../slang-utils/is-label.js'; import { printGroupAndIndentIfBreakPair } from '../slang-printers/print-group-and-indent-if-break-pair.js'; import { printVariant } from '../slang-printers/print-variant.js'; +import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { Expression } from './Expression.js'; import { ArgumentsDeclaration } from './ArgumentsDeclaration.js'; @@ -19,7 +20,7 @@ export class FunctionCallExpression extends SlangNode { operand: Expression; - arguments: ArgumentsDeclaration; + arguments: ArgumentsDeclaration['variant']; constructor( ast: ast.FunctionCallExpression, @@ -28,14 +29,16 @@ export class FunctionCallExpression extends SlangNode { super(ast); this.operand = new Expression(ast.operand, options); - this.arguments = new ArgumentsDeclaration(ast.arguments, options); + this.arguments = extractVariant( + new ArgumentsDeclaration(ast.arguments, options) + ); this.updateMetadata(this.operand, this.arguments); } print(path: AstPath, print: PrintFunction): Doc { const operand = path.call(printVariant(print), 'operand'); - const argumentsDoc = path.call(printVariant(print), 'arguments'); + const argumentsDoc = path.call(print, 'arguments'); // If we are at the end of a MemberAccessChain we should indent the // arguments accordingly. diff --git a/src/slang-nodes/InheritanceType.ts b/src/slang-nodes/InheritanceType.ts index b45d24c63..55510600e 100644 --- a/src/slang-nodes/InheritanceType.ts +++ b/src/slang-nodes/InheritanceType.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printVariant } from '../slang-printers/print-variant.js'; +import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { IdentifierPath } from './IdentifierPath.js'; import { ArgumentsDeclaration } from './ArgumentsDeclaration.js'; @@ -14,23 +14,22 @@ export class InheritanceType extends SlangNode { typeName: IdentifierPath; - arguments?: ArgumentsDeclaration; + arguments?: ArgumentsDeclaration['variant']; constructor(ast: ast.InheritanceType, options: ParserOptions) { super(ast); this.typeName = new IdentifierPath(ast.typeName); if (ast.arguments) { - this.arguments = new ArgumentsDeclaration(ast.arguments, options); + this.arguments = extractVariant( + new ArgumentsDeclaration(ast.arguments, options) + ); } this.updateMetadata(this.typeName, this.arguments); } print(path: AstPath, print: PrintFunction): Doc { - return [ - path.call(print, 'typeName'), - path.call(printVariant(print), 'arguments') - ]; + return [path.call(print, 'typeName'), path.call(print, 'arguments')]; } } diff --git a/src/slang-nodes/ModifierInvocation.ts b/src/slang-nodes/ModifierInvocation.ts index 6eea4454e..378a43e34 100644 --- a/src/slang-nodes/ModifierInvocation.ts +++ b/src/slang-nodes/ModifierInvocation.ts @@ -1,5 +1,5 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; -import { printVariant } from '../slang-printers/print-variant.js'; +import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { IdentifierPath } from './IdentifierPath.js'; import { ArgumentsDeclaration } from './ArgumentsDeclaration.js'; @@ -14,35 +14,32 @@ export class ModifierInvocation extends SlangNode { name: IdentifierPath; - arguments?: ArgumentsDeclaration; + arguments?: ArgumentsDeclaration['variant']; constructor(ast: ast.ModifierInvocation, options: ParserOptions) { super(ast); this.name = new IdentifierPath(ast.name); if (ast.arguments) { - this.arguments = new ArgumentsDeclaration(ast.arguments, options); + this.arguments = extractVariant( + new ArgumentsDeclaration(ast.arguments, options) + ); } this.updateMetadata(this.name, this.arguments); } cleanModifierInvocationArguments(): void { - const argumentsVariant = this.arguments?.variant; if ( - argumentsVariant && - argumentsVariant.kind === - NonterminalKind.PositionalArgumentsDeclaration && - argumentsVariant.isEmpty + this.arguments && + this.arguments.kind === NonterminalKind.PositionalArgumentsDeclaration && + this.arguments.isEmpty ) { delete this.arguments; } } print(path: AstPath, print: PrintFunction): Doc { - return [ - path.call(print, 'name'), - path.call(printVariant(print), 'arguments') - ]; + return [path.call(print, 'name'), path.call(print, 'arguments')]; } } diff --git a/src/slang-nodes/RevertStatement.ts b/src/slang-nodes/RevertStatement.ts index 7019b78f9..cbbf5f010 100644 --- a/src/slang-nodes/RevertStatement.ts +++ b/src/slang-nodes/RevertStatement.ts @@ -1,6 +1,6 @@ import { NonterminalKind } from '@nomicfoundation/slang/cst'; import { joinExisting } from '../slang-utils/join-existing.js'; -import { printVariant } from '../slang-printers/print-variant.js'; +import { extractVariant } from '../slang-utils/extract-variant.js'; import { SlangNode } from './SlangNode.js'; import { IdentifierPath } from './IdentifierPath.js'; import { ArgumentsDeclaration } from './ArgumentsDeclaration.js'; @@ -15,7 +15,7 @@ export class RevertStatement extends SlangNode { error?: IdentifierPath; - arguments: ArgumentsDeclaration; + arguments: ArgumentsDeclaration['variant']; constructor(ast: ast.RevertStatement, options: ParserOptions) { super(ast); @@ -23,7 +23,9 @@ export class RevertStatement extends SlangNode { if (ast.error) { this.error = new IdentifierPath(ast.error); } - this.arguments = new ArgumentsDeclaration(ast.arguments, options); + this.arguments = extractVariant( + new ArgumentsDeclaration(ast.arguments, options) + ); this.updateMetadata(this.error, this.arguments); } @@ -31,7 +33,7 @@ export class RevertStatement extends SlangNode { print(path: AstPath, print: PrintFunction): Doc { return [ joinExisting(' ', ['revert', path.call(print, 'error')]), - path.call(printVariant(print), 'arguments'), + path.call(print, 'arguments'), ';' ]; } diff --git a/src/slang-utils/extract-variant.ts b/src/slang-utils/extract-variant.ts new file mode 100644 index 000000000..4ded9b6e4 --- /dev/null +++ b/src/slang-utils/extract-variant.ts @@ -0,0 +1,9 @@ +import type { StrictPolymorphicNode } from '../slang-nodes/types.ts'; + +export function extractVariant({ + variant, + loc +}: T): T['variant'] { + variant.loc = loc; + return variant; +} diff --git a/src/slangPrinter.ts b/src/slangPrinter.ts index 497e3c7fd..7b0ad1a55 100644 --- a/src/slangPrinter.ts +++ b/src/slangPrinter.ts @@ -4,6 +4,7 @@ import { locEnd, locStart } from './slang-utils/loc.js'; import type { AstPath, Doc, ParserOptions } from 'prettier'; import type { AstNode, StrictAstNode } from './slang-nodes/types.d.ts'; import type { PrintFunction } from './types.d.ts'; +import type { ArgumentsDeclaration } from './slang-nodes/ArgumentsDeclaration.js'; function hasNodeIgnoreComment({ comments }: StrictAstNode): boolean { // Prettier sets SourceUnit's comments to undefined after assigning comments @@ -30,7 +31,6 @@ function ignoreComments(path: AstPath): void { // parser. `updateMetadata` is an internal function. case 'kind': case 'loc': - case 'print': case 'updateMetadata': break; // The key `comments` will contain every comment for this node. @@ -54,7 +54,7 @@ function ignoreComments(path: AstPath): void { // Nodes take care of undefined and string properties so we can restrict path // to AstPath function genericPrint( - path: AstPath, + path: AstPath>, options: ParserOptions, print: PrintFunction ): Doc {