From c87a687e5451bc64e2d863bbc5b78ac4e716bdb7 Mon Sep 17 00:00:00 2001 From: blitz-1306 Date: Thu, 12 Aug 2021 10:49:58 +0500 Subject: [PATCH 1/4] Introduced EnumDefinition.toUintTypeString() by moving related code from VariableDeclaration.canonicalSignatureType(). Introduced priority support for AST postprocessing logic. --- src/ast/ast_node_factory.ts | 7 +- src/ast/ast_reader.ts | 33 +--------- .../declaration/enum_definition.ts | 12 ++++ .../declaration/variable_declaration.ts | 12 +--- ...iltin_referenced_declaration_normalizer.ts | 5 +- src/ast/postprocessing/index.ts | 1 + src/ast/postprocessing/mapping.ts | 28 ++++---- src/ast/postprocessing/postprocessor.ts | 66 +++++++++++++++++++ ...structured_documentation_reconstruction.ts | 5 +- src/ast/writing/ast_mapping.ts | 7 +- 10 files changed, 110 insertions(+), 66 deletions(-) create mode 100644 src/ast/postprocessing/postprocessor.ts diff --git a/src/ast/ast_node_factory.ts b/src/ast/ast_node_factory.ts index 77c488fd..b7eb7776 100644 --- a/src/ast/ast_node_factory.ts +++ b/src/ast/ast_node_factory.ts @@ -1,5 +1,5 @@ import { ASTNode, ASTNodeConstructor } from "./ast_node"; -import { ASTContext, ASTPostprocessor } from "./ast_reader"; +import { ASTContext } from "./ast_reader"; import { FunctionStateMutability, FunctionVisibility } from "./constants"; import { ContractDefinition } from "./implementation/declaration/contract_definition"; import { EnumDefinition } from "./implementation/declaration/enum_definition"; @@ -61,6 +61,7 @@ import { FunctionTypeName } from "./implementation/type/function_type_name"; import { Mapping } from "./implementation/type/mapping"; import { TypeName } from "./implementation/type/type_name"; import { UserDefinedTypeName } from "./implementation/type/user_defined_type_name"; +import { ASTPostprocessor } from "./postprocessing"; /** * When applied to following tuple type: @@ -1087,7 +1088,7 @@ export class ASTNodeFactory { ): T { const node = this.makeUnfinalized(type, ...args); - this.postprocessor.process(node, this.context); + this.postprocessor.processNode(node, this.context); return node; } @@ -1101,7 +1102,7 @@ export class ASTNodeFactory { for (const child of clone.getChildren(true)) { this.patchIds(child, cache); - postprocessor.process(child, context); + postprocessor.processNode(child, context); } return clone; diff --git a/src/ast/ast_reader.ts b/src/ast/ast_reader.ts index b692e86d..045437e5 100644 --- a/src/ast/ast_reader.ts +++ b/src/ast/ast_reader.ts @@ -2,7 +2,7 @@ import { ASTNode, ASTNodeConstructor } from "./ast_node"; import { SourceUnit } from "./implementation/meta/source_unit"; import { LegacyConfiguration } from "./legacy"; import { ModernConfiguration } from "./modern"; -import { DefaultPostprocessorMapping } from "./postprocessing/mapping"; +import { ASTPostprocessor } from "./postprocessing/postprocessor"; import { sequence } from "./utils"; export interface ASTNodeProcessor { @@ -115,30 +115,6 @@ export class ASTContext { } } -export interface ASTNodePostprocessor { - process(node: ASTNode, context: ASTContext, sources?: Map): void; -} - -export class ASTPostprocessor { - mapping: Map, ASTNodePostprocessor[]>; - - constructor(mapping = DefaultPostprocessorMapping) { - this.mapping = mapping; - } - - process(node: ASTNode, context: ASTContext, sources?: Map): void { - const postprocessors = this.mapping.get(node.constructor as ASTNodeConstructor); - - if (postprocessors === undefined) { - return; - } - - for (const postprocessor of postprocessors) { - postprocessor.process(node, context, sources); - } - } -} - export enum ASTKind { Any = "any", Modern = "modern", @@ -209,12 +185,7 @@ export class ASTReader { result.push(sourceUnit); } - const context = this.context; - const postprocessor = this.postprocessor; - - for (const node of context.nodes) { - postprocessor.process(node, context, sources); - } + this.postprocessor.processContext(this.context, sources); return result; } diff --git a/src/ast/implementation/declaration/enum_definition.ts b/src/ast/implementation/declaration/enum_definition.ts index c10a02f5..a74eea32 100644 --- a/src/ast/implementation/declaration/enum_definition.ts +++ b/src/ast/implementation/declaration/enum_definition.ts @@ -54,4 +54,16 @@ export class EnumDefinition extends ASTNodeWithChildren { get vScope(): ContractDefinition | SourceUnit { return this.parent as ContractDefinition | SourceUnit; } + + toUintTypeString(): string { + const length = this.children.length; + + for (let n = 8; n <= 32; n += 8) { + if (length < 2 ** n) { + return "uint" + n; + } + } + + throw new Error("Unable to detect enum type size - member count exceeds 2 ** 32"); + } } diff --git a/src/ast/implementation/declaration/variable_declaration.ts b/src/ast/implementation/declaration/variable_declaration.ts index b6051415..6ce32eb1 100644 --- a/src/ast/implementation/declaration/variable_declaration.ts +++ b/src/ast/implementation/declaration/variable_declaration.ts @@ -184,17 +184,7 @@ export class VariableDeclaration extends ASTNode { } if (declaration instanceof EnumDefinition) { - const length = declaration.children.length; - - for (let n = 8; n <= 32; n += 8) { - if (length < 2 ** n) { - return "uint" + n; - } - } - - throw new Error( - "Unable to detect enum type size - member count exceeds 2 ** 32" - ); + return declaration.toUintTypeString(); } } diff --git a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts index 09c382b6..24dd175a 100644 --- a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts +++ b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts @@ -1,13 +1,14 @@ import { ASTNode } from "../ast_node"; -import { ASTContext, ASTNodePostprocessor } from "../ast_reader"; +import { ASTContext } from "../ast_reader"; import { Identifier } from "../implementation/expression/identifier"; import { MemberAccess } from "../implementation/expression/member_access"; import { IdentifierPath } from "../implementation/meta/identifier_path"; import { UserDefinedTypeName } from "../implementation/type/user_defined_type_name"; +import { ASTNodePostprocessor } from "./postprocessor"; type SupportedNode = Identifier | MemberAccess | IdentifierPath | UserDefinedTypeName; -export class BuiltinReferencedDeclarationNormalizer implements ASTNodePostprocessor { +export class BuiltinReferencedDeclarationNormalizer extends ASTNodePostprocessor { process(node: ASTNode, context: ASTContext): void { if (!this.isSupportedNode(node)) { throw new Error(`Supplied node "${node.constructor.name}" is not supported`); diff --git a/src/ast/postprocessing/index.ts b/src/ast/postprocessing/index.ts index 34afc21c..2144eb82 100644 --- a/src/ast/postprocessing/index.ts +++ b/src/ast/postprocessing/index.ts @@ -1,3 +1,4 @@ export * from "./mapping"; export * from "./builtin_referenced_declaration_normalizer"; export * from "./structured_documentation_reconstruction"; +export * from "./postprocessor"; diff --git a/src/ast/postprocessing/mapping.ts b/src/ast/postprocessing/mapping.ts index ec09f0a0..2e286c88 100644 --- a/src/ast/postprocessing/mapping.ts +++ b/src/ast/postprocessing/mapping.ts @@ -1,5 +1,4 @@ import { ASTNode, ASTNodeConstructor } from "../ast_node"; -import { ASTNodePostprocessor } from "../ast_reader"; import { ContractDefinition } from "../implementation/declaration/contract_definition"; import { EventDefinition } from "../implementation/declaration/event_definition"; import { FunctionDefinition } from "../implementation/declaration/function_definition"; @@ -10,23 +9,28 @@ import { MemberAccess } from "../implementation/expression/member_access"; import { IdentifierPath } from "../implementation/meta/identifier_path"; import { UserDefinedTypeName } from "../implementation/type/user_defined_type_name"; import { BuiltinReferencedDeclarationNormalizer } from "./builtin_referenced_declaration_normalizer"; +import { ASTNodePostprocessor } from "./postprocessor"; import { StructuredDocumentationReconstructingPostprocessor } from "./structured_documentation_reconstruction"; -const reconstructor = new StructuredDocumentationReconstructingPostprocessor(); -const refNormalizer = new BuiltinReferencedDeclarationNormalizer(); +const reconstructor = new StructuredDocumentationReconstructingPostprocessor(1000); +const refNormalizer = new BuiltinReferencedDeclarationNormalizer(100); + +function sortByPriority(a: ASTNodePostprocessor, b: ASTNodePostprocessor): number { + return a.priority - b.priority; +} export const DefaultPostprocessorMapping = new Map< ASTNodeConstructor, ASTNodePostprocessor[] >([ - [ContractDefinition, [reconstructor]], - [EventDefinition, [reconstructor]], - [FunctionDefinition, [reconstructor]], - [ModifierDefinition, [reconstructor]], - [VariableDeclaration, [reconstructor]], + [ContractDefinition, [reconstructor].sort(sortByPriority)], + [EventDefinition, [reconstructor].sort(sortByPriority)], + [FunctionDefinition, [reconstructor].sort(sortByPriority)], + [ModifierDefinition, [reconstructor].sort(sortByPriority)], + [VariableDeclaration, [reconstructor].sort(sortByPriority)], - [Identifier, [refNormalizer]], - [MemberAccess, [refNormalizer]], - [IdentifierPath, [refNormalizer]], - [UserDefinedTypeName, [refNormalizer]] + [Identifier, [refNormalizer].sort(sortByPriority)], + [MemberAccess, [refNormalizer].sort(sortByPriority)], + [IdentifierPath, [refNormalizer].sort(sortByPriority)], + [UserDefinedTypeName, [refNormalizer].sort(sortByPriority)] ]); diff --git a/src/ast/postprocessing/postprocessor.ts b/src/ast/postprocessing/postprocessor.ts new file mode 100644 index 00000000..dcfce7e5 --- /dev/null +++ b/src/ast/postprocessing/postprocessor.ts @@ -0,0 +1,66 @@ +import { ASTNode, ASTNodeConstructor } from "../ast_node"; +import { ASTContext } from "../ast_reader"; +import { DefaultPostprocessorMapping } from "./mapping"; + +export abstract class ASTNodePostprocessor { + readonly priority: number; + + constructor(priority: number) { + this.priority = priority; + } + + abstract process(node: ASTNode, context: ASTContext, sources?: Map): void; +} + +export class ASTPostprocessor { + mapping: Map, ASTNodePostprocessor[]>; + + constructor(mapping = DefaultPostprocessorMapping) { + this.mapping = mapping; + } + + getPostprocessorsForNode(node: ASTNode): ASTNodePostprocessor[] | undefined { + return this.mapping.get(node.constructor as ASTNodeConstructor); + } + + processNode(node: ASTNode, context: ASTContext, sources?: Map): void { + const postprocessors = this.getPostprocessorsForNode(node); + + if (postprocessors) { + for (const postprocessor of postprocessors) { + postprocessor.process(node, context, sources); + } + } + } + + processContext(context: ASTContext, sources?: Map): void { + const groupsByPriority = new Map(); + + for (const node of context.nodes) { + const postprocessors = this.getPostprocessorsForNode(node); + + if (postprocessors) { + for (const postprocessor of postprocessors) { + const priority = postprocessor.priority; + const group = groupsByPriority.get(priority); + + if (group) { + group.push(node); + } else { + groupsByPriority.set(priority, [node]); + } + } + } + } + + const groups = Array.from(groupsByPriority) + .sort((a, b) => a[0] - b[0]) + .map((entry) => entry[1]); + + for (const nodes of groups) { + for (const node of nodes) { + this.processNode(node, context, sources); + } + } + } +} diff --git a/src/ast/postprocessing/structured_documentation_reconstruction.ts b/src/ast/postprocessing/structured_documentation_reconstruction.ts index 5f5d2c67..767192b5 100644 --- a/src/ast/postprocessing/structured_documentation_reconstruction.ts +++ b/src/ast/postprocessing/structured_documentation_reconstruction.ts @@ -1,5 +1,5 @@ import { ASTNode } from "../ast_node"; -import { ASTContext, ASTNodePostprocessor } from "../ast_reader"; +import { ASTContext } from "../ast_reader"; import { ContractDefinition, ErrorDefinition, @@ -10,6 +10,7 @@ import { } from "../implementation/declaration"; import { SourceUnit } from "../implementation/meta/source_unit"; import { StructuredDocumentation } from "../implementation/meta/structured_documentation"; +import { ASTNodePostprocessor } from "./postprocessor"; export class StructuredDocumentationReconstructor { process(node: ASTNode, source: string): StructuredDocumentation | undefined { @@ -126,7 +127,7 @@ type SupportedNode = | EventDefinition | ModifierDefinition; -export class StructuredDocumentationReconstructingPostprocessor implements ASTNodePostprocessor { +export class StructuredDocumentationReconstructingPostprocessor extends ASTNodePostprocessor { private reconstructor = new StructuredDocumentationReconstructor(); process(node: ASTNode, context: ASTContext, sources?: Map): void { diff --git a/src/ast/writing/ast_mapping.ts b/src/ast/writing/ast_mapping.ts index 65ed5842..32a4a90e 100644 --- a/src/ast/writing/ast_mapping.ts +++ b/src/ast/writing/ast_mapping.ts @@ -1305,7 +1305,7 @@ class SourceUnitWriter extends ASTNodeWriter { result.push(...flatten(node.vImportDirectives.map(writeLineFn)), wrap); } - const typeDefs = node.vEnums.concat(node.vStructs); + const typeDefs = [...node.vEnums, ...node.vStructs]; if (typeDefs.length > 0) { result.push(...flatJoin(typeDefs.map(writeLineFn), wrap), wrap); @@ -1315,10 +1315,7 @@ class SourceUnitWriter extends ASTNodeWriter { result.push(...flatten(node.vVariables.map((n) => [...writeFn(n), ";", wrap])), wrap); } - const otherDefs = (node.vErrors as readonly ASTNode[]).concat( - node.vFunctions, - node.vContracts - ); + const otherDefs = [...node.vErrors, ...node.vFunctions, ...node.vContracts]; if (otherDefs.length > 0) { result.push(...flatJoin(otherDefs.map(writeLineFn), wrap)); From e1e6d9c05b37d34d5b5b8a516a5e4778ecc8cb27 Mon Sep 17 00:00:00 2001 From: blitz-1306 Date: Thu, 12 Aug 2021 12:13:51 +0500 Subject: [PATCH 2/4] Moved basic postprocessor implementation to a standalone file, fixed imports. --- src/ast/ast_node_factory.ts | 3 +- src/ast/ast_reader.ts | 61 ++++++++++++++++- ...iltin_referenced_declaration_normalizer.ts | 4 +- src/ast/postprocessing/index.ts | 4 +- src/ast/postprocessing/mapping.ts | 2 +- src/ast/postprocessing/node_postprocessor.ts | 12 ++++ src/ast/postprocessing/postprocessor.ts | 66 ------------------- ...structured_documentation_reconstruction.ts | 4 +- 8 files changed, 80 insertions(+), 76 deletions(-) create mode 100644 src/ast/postprocessing/node_postprocessor.ts delete mode 100644 src/ast/postprocessing/postprocessor.ts diff --git a/src/ast/ast_node_factory.ts b/src/ast/ast_node_factory.ts index b7eb7776..65f0cad6 100644 --- a/src/ast/ast_node_factory.ts +++ b/src/ast/ast_node_factory.ts @@ -1,5 +1,5 @@ import { ASTNode, ASTNodeConstructor } from "./ast_node"; -import { ASTContext } from "./ast_reader"; +import { ASTContext, ASTPostprocessor } from "./ast_reader"; import { FunctionStateMutability, FunctionVisibility } from "./constants"; import { ContractDefinition } from "./implementation/declaration/contract_definition"; import { EnumDefinition } from "./implementation/declaration/enum_definition"; @@ -61,7 +61,6 @@ import { FunctionTypeName } from "./implementation/type/function_type_name"; import { Mapping } from "./implementation/type/mapping"; import { TypeName } from "./implementation/type/type_name"; import { UserDefinedTypeName } from "./implementation/type/user_defined_type_name"; -import { ASTPostprocessor } from "./postprocessing"; /** * When applied to following tuple type: diff --git a/src/ast/ast_reader.ts b/src/ast/ast_reader.ts index 045437e5..13b22f09 100644 --- a/src/ast/ast_reader.ts +++ b/src/ast/ast_reader.ts @@ -2,7 +2,7 @@ import { ASTNode, ASTNodeConstructor } from "./ast_node"; import { SourceUnit } from "./implementation/meta/source_unit"; import { LegacyConfiguration } from "./legacy"; import { ModernConfiguration } from "./modern"; -import { ASTPostprocessor } from "./postprocessing/postprocessor"; +import { DefaultPostprocessorMapping } from "./postprocessing"; import { sequence } from "./utils"; export interface ASTNodeProcessor { @@ -13,6 +13,12 @@ export interface ASTNodeProcessor { ): ConstructorParameters>; } +export interface ASTNodePostprocessor { + readonly priority: number; + + process(node: ASTNode, context: ASTContext, sources?: Map): void; +} + export interface ASTReadingRule { constructor: ASTNodeConstructor; processor: ASTNodeProcessor; @@ -115,6 +121,59 @@ export class ASTContext { } } +export class ASTPostprocessor { + mapping: Map, ASTNodePostprocessor[]>; + + constructor(mapping = DefaultPostprocessorMapping) { + this.mapping = mapping; + } + + getPostprocessorsForNode(node: ASTNode): ASTNodePostprocessor[] | undefined { + return this.mapping.get(node.constructor as ASTNodeConstructor); + } + + processNode(node: ASTNode, context: ASTContext, sources?: Map): void { + const postprocessors = this.getPostprocessorsForNode(node); + + if (postprocessors) { + for (const postprocessor of postprocessors) { + postprocessor.process(node, context, sources); + } + } + } + + processContext(context: ASTContext, sources?: Map): void { + const groupsByPriority = new Map(); + + for (const node of context.nodes) { + const postprocessors = this.getPostprocessorsForNode(node); + + if (postprocessors) { + for (const postprocessor of postprocessors) { + const priority = postprocessor.priority; + const group = groupsByPriority.get(priority); + + if (group) { + group.push(node); + } else { + groupsByPriority.set(priority, [node]); + } + } + } + } + + const groups = Array.from(groupsByPriority) + .sort((a, b) => a[0] - b[0]) + .map((entry) => entry[1]); + + for (const nodes of groups) { + for (const node of nodes) { + this.processNode(node, context, sources); + } + } + } +} + export enum ASTKind { Any = "any", Modern = "modern", diff --git a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts index 24dd175a..1e9db368 100644 --- a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts +++ b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts @@ -4,11 +4,11 @@ import { Identifier } from "../implementation/expression/identifier"; import { MemberAccess } from "../implementation/expression/member_access"; import { IdentifierPath } from "../implementation/meta/identifier_path"; import { UserDefinedTypeName } from "../implementation/type/user_defined_type_name"; -import { ASTNodePostprocessor } from "./postprocessor"; +import { NodePostprocessor } from "./node_postprocessor"; type SupportedNode = Identifier | MemberAccess | IdentifierPath | UserDefinedTypeName; -export class BuiltinReferencedDeclarationNormalizer extends ASTNodePostprocessor { +export class BuiltinReferencedDeclarationNormalizer extends NodePostprocessor { process(node: ASTNode, context: ASTContext): void { if (!this.isSupportedNode(node)) { throw new Error(`Supplied node "${node.constructor.name}" is not supported`); diff --git a/src/ast/postprocessing/index.ts b/src/ast/postprocessing/index.ts index 2144eb82..90e5bea4 100644 --- a/src/ast/postprocessing/index.ts +++ b/src/ast/postprocessing/index.ts @@ -1,4 +1,4 @@ -export * from "./mapping"; export * from "./builtin_referenced_declaration_normalizer"; +export * from "./mapping"; +export * from "./node_postprocessor"; export * from "./structured_documentation_reconstruction"; -export * from "./postprocessor"; diff --git a/src/ast/postprocessing/mapping.ts b/src/ast/postprocessing/mapping.ts index 2e286c88..1abbfe53 100644 --- a/src/ast/postprocessing/mapping.ts +++ b/src/ast/postprocessing/mapping.ts @@ -1,4 +1,5 @@ import { ASTNode, ASTNodeConstructor } from "../ast_node"; +import { ASTNodePostprocessor } from "../ast_reader"; import { ContractDefinition } from "../implementation/declaration/contract_definition"; import { EventDefinition } from "../implementation/declaration/event_definition"; import { FunctionDefinition } from "../implementation/declaration/function_definition"; @@ -9,7 +10,6 @@ import { MemberAccess } from "../implementation/expression/member_access"; import { IdentifierPath } from "../implementation/meta/identifier_path"; import { UserDefinedTypeName } from "../implementation/type/user_defined_type_name"; import { BuiltinReferencedDeclarationNormalizer } from "./builtin_referenced_declaration_normalizer"; -import { ASTNodePostprocessor } from "./postprocessor"; import { StructuredDocumentationReconstructingPostprocessor } from "./structured_documentation_reconstruction"; const reconstructor = new StructuredDocumentationReconstructingPostprocessor(1000); diff --git a/src/ast/postprocessing/node_postprocessor.ts b/src/ast/postprocessing/node_postprocessor.ts new file mode 100644 index 00000000..36f24856 --- /dev/null +++ b/src/ast/postprocessing/node_postprocessor.ts @@ -0,0 +1,12 @@ +import { ASTNode } from "../ast_node"; +import { ASTContext, ASTNodePostprocessor } from "../ast_reader"; + +export abstract class NodePostprocessor implements ASTNodePostprocessor { + readonly priority: number; + + constructor(priority: number) { + this.priority = priority; + } + + abstract process(node: ASTNode, context: ASTContext, sources?: Map): void; +} diff --git a/src/ast/postprocessing/postprocessor.ts b/src/ast/postprocessing/postprocessor.ts deleted file mode 100644 index dcfce7e5..00000000 --- a/src/ast/postprocessing/postprocessor.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { ASTNode, ASTNodeConstructor } from "../ast_node"; -import { ASTContext } from "../ast_reader"; -import { DefaultPostprocessorMapping } from "./mapping"; - -export abstract class ASTNodePostprocessor { - readonly priority: number; - - constructor(priority: number) { - this.priority = priority; - } - - abstract process(node: ASTNode, context: ASTContext, sources?: Map): void; -} - -export class ASTPostprocessor { - mapping: Map, ASTNodePostprocessor[]>; - - constructor(mapping = DefaultPostprocessorMapping) { - this.mapping = mapping; - } - - getPostprocessorsForNode(node: ASTNode): ASTNodePostprocessor[] | undefined { - return this.mapping.get(node.constructor as ASTNodeConstructor); - } - - processNode(node: ASTNode, context: ASTContext, sources?: Map): void { - const postprocessors = this.getPostprocessorsForNode(node); - - if (postprocessors) { - for (const postprocessor of postprocessors) { - postprocessor.process(node, context, sources); - } - } - } - - processContext(context: ASTContext, sources?: Map): void { - const groupsByPriority = new Map(); - - for (const node of context.nodes) { - const postprocessors = this.getPostprocessorsForNode(node); - - if (postprocessors) { - for (const postprocessor of postprocessors) { - const priority = postprocessor.priority; - const group = groupsByPriority.get(priority); - - if (group) { - group.push(node); - } else { - groupsByPriority.set(priority, [node]); - } - } - } - } - - const groups = Array.from(groupsByPriority) - .sort((a, b) => a[0] - b[0]) - .map((entry) => entry[1]); - - for (const nodes of groups) { - for (const node of nodes) { - this.processNode(node, context, sources); - } - } - } -} diff --git a/src/ast/postprocessing/structured_documentation_reconstruction.ts b/src/ast/postprocessing/structured_documentation_reconstruction.ts index 767192b5..ce4f411f 100644 --- a/src/ast/postprocessing/structured_documentation_reconstruction.ts +++ b/src/ast/postprocessing/structured_documentation_reconstruction.ts @@ -10,7 +10,7 @@ import { } from "../implementation/declaration"; import { SourceUnit } from "../implementation/meta/source_unit"; import { StructuredDocumentation } from "../implementation/meta/structured_documentation"; -import { ASTNodePostprocessor } from "./postprocessor"; +import { NodePostprocessor } from "./node_postprocessor"; export class StructuredDocumentationReconstructor { process(node: ASTNode, source: string): StructuredDocumentation | undefined { @@ -127,7 +127,7 @@ type SupportedNode = | EventDefinition | ModifierDefinition; -export class StructuredDocumentationReconstructingPostprocessor extends ASTNodePostprocessor { +export class StructuredDocumentationReconstructingPostprocessor extends NodePostprocessor { private reconstructor = new StructuredDocumentationReconstructor(); process(node: ASTNode, context: ASTContext, sources?: Map): void { From 77d1a8134ac36f4df3ef052e8412481117dfc4d4 Mon Sep 17 00:00:00 2001 From: blitz-1306 Date: Wed, 25 Aug 2021 12:39:10 +0500 Subject: [PATCH 3/4] Reimplemented postprocessing-by-priority solution --- src/ast/ast_reader.ts | 53 ++++++++----------- ...iltin_referenced_declaration_normalizer.ts | 10 ++-- src/ast/postprocessing/index.ts | 2 +- src/ast/postprocessing/list.ts | 14 +++++ src/ast/postprocessing/mapping.ts | 36 ------------- src/ast/postprocessing/node_postprocessor.ts | 5 +- ...structured_documentation_reconstruction.ts | 10 ++-- 7 files changed, 45 insertions(+), 85 deletions(-) create mode 100644 src/ast/postprocessing/list.ts delete mode 100644 src/ast/postprocessing/mapping.ts diff --git a/src/ast/ast_reader.ts b/src/ast/ast_reader.ts index 13b22f09..5265ea12 100644 --- a/src/ast/ast_reader.ts +++ b/src/ast/ast_reader.ts @@ -2,7 +2,7 @@ import { ASTNode, ASTNodeConstructor } from "./ast_node"; import { SourceUnit } from "./implementation/meta/source_unit"; import { LegacyConfiguration } from "./legacy"; import { ModernConfiguration } from "./modern"; -import { DefaultPostprocessorMapping } from "./postprocessing"; +import { DefaultNodePostprocessorList } from "./postprocessing"; import { sequence } from "./utils"; export interface ASTNodeProcessor { @@ -13,10 +13,11 @@ export interface ASTNodeProcessor { ): ConstructorParameters>; } -export interface ASTNodePostprocessor { +export interface ASTNodePostprocessor { readonly priority: number; - process(node: ASTNode, context: ASTContext, sources?: Map): void; + process(node: T, context: ASTContext, sources?: Map): void; + isSupportedNode(node: ASTNode): node is T; } export interface ASTReadingRule { @@ -122,53 +123,41 @@ export class ASTContext { } export class ASTPostprocessor { - mapping: Map, ASTNodePostprocessor[]>; + nodePostprocessors: ReadonlyArray>; - constructor(mapping = DefaultPostprocessorMapping) { - this.mapping = mapping; + constructor(nodePostProcessors = DefaultNodePostprocessorList) { + this.nodePostprocessors = nodePostProcessors.sort((a, b) => b.priority - a.priority); } - getPostprocessorsForNode(node: ASTNode): ASTNodePostprocessor[] | undefined { - return this.mapping.get(node.constructor as ASTNodeConstructor); + getPostprocessorsForNode(node: ASTNode): Array> { + return this.nodePostprocessors.filter((postprocessor) => + postprocessor.isSupportedNode(node) + ); } processNode(node: ASTNode, context: ASTContext, sources?: Map): void { const postprocessors = this.getPostprocessorsForNode(node); - if (postprocessors) { - for (const postprocessor of postprocessors) { - postprocessor.process(node, context, sources); - } + for (const postprocessor of postprocessors) { + postprocessor.process(node, context, sources); } } processContext(context: ASTContext, sources?: Map): void { - const groupsByPriority = new Map(); - - for (const node of context.nodes) { - const postprocessors = this.getPostprocessorsForNode(node); + const groups: Array<[ASTNodePostprocessor, ASTNode[]]> = + this.nodePostprocessors.map((postprocessor) => [postprocessor, []]); - if (postprocessors) { - for (const postprocessor of postprocessors) { - const priority = postprocessor.priority; - const group = groupsByPriority.get(priority); - - if (group) { - group.push(node); - } else { - groupsByPriority.set(priority, [node]); - } + for (const [postprocessor, nodes] of groups) { + for (const node of context.nodes) { + if (postprocessor.isSupportedNode(node)) { + nodes.push(node); } } } - const groups = Array.from(groupsByPriority) - .sort((a, b) => a[0] - b[0]) - .map((entry) => entry[1]); - - for (const nodes of groups) { + for (const [postprocessor, nodes] of groups) { for (const node of nodes) { - this.processNode(node, context, sources); + postprocessor.process(node, context, sources); } } } diff --git a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts index 1e9db368..fa8430bb 100644 --- a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts +++ b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts @@ -8,12 +8,8 @@ import { NodePostprocessor } from "./node_postprocessor"; type SupportedNode = Identifier | MemberAccess | IdentifierPath | UserDefinedTypeName; -export class BuiltinReferencedDeclarationNormalizer extends NodePostprocessor { - process(node: ASTNode, context: ASTContext): void { - if (!this.isSupportedNode(node)) { - throw new Error(`Supplied node "${node.constructor.name}" is not supported`); - } - +export class BuiltinReferencedDeclarationNormalizer extends NodePostprocessor { + process(node: SupportedNode, context: ASTContext): void { if ( node.referencedDeclaration >= 0 && context.locate(node.referencedDeclaration) === undefined @@ -22,7 +18,7 @@ export class BuiltinReferencedDeclarationNormalizer extends NodePostprocessor { } } - private isSupportedNode(node: ASTNode): node is SupportedNode { + isSupportedNode(node: ASTNode): node is SupportedNode { return ( node instanceof Identifier || node instanceof MemberAccess || diff --git a/src/ast/postprocessing/index.ts b/src/ast/postprocessing/index.ts index 90e5bea4..432b922a 100644 --- a/src/ast/postprocessing/index.ts +++ b/src/ast/postprocessing/index.ts @@ -1,4 +1,4 @@ export * from "./builtin_referenced_declaration_normalizer"; -export * from "./mapping"; +export * from "./list"; export * from "./node_postprocessor"; export * from "./structured_documentation_reconstruction"; diff --git a/src/ast/postprocessing/list.ts b/src/ast/postprocessing/list.ts new file mode 100644 index 00000000..d173056a --- /dev/null +++ b/src/ast/postprocessing/list.ts @@ -0,0 +1,14 @@ +import { ASTNode } from "../ast_node"; +import { ASTNodePostprocessor } from "../ast_reader"; +import { BuiltinReferencedDeclarationNormalizer } from "./builtin_referenced_declaration_normalizer"; +import { StructuredDocumentationReconstructingPostprocessor } from "./structured_documentation_reconstruction"; + +/** + * Higher priority value means earlier execution. + * Do not use same priority values for different node postprocessors + * (may result unpredictable behavior). + */ +export const DefaultNodePostprocessorList: Array> = [ + new BuiltinReferencedDeclarationNormalizer(1000), + new StructuredDocumentationReconstructingPostprocessor(100) +]; diff --git a/src/ast/postprocessing/mapping.ts b/src/ast/postprocessing/mapping.ts deleted file mode 100644 index 1abbfe53..00000000 --- a/src/ast/postprocessing/mapping.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ASTNode, ASTNodeConstructor } from "../ast_node"; -import { ASTNodePostprocessor } from "../ast_reader"; -import { ContractDefinition } from "../implementation/declaration/contract_definition"; -import { EventDefinition } from "../implementation/declaration/event_definition"; -import { FunctionDefinition } from "../implementation/declaration/function_definition"; -import { ModifierDefinition } from "../implementation/declaration/modifier_definition"; -import { VariableDeclaration } from "../implementation/declaration/variable_declaration"; -import { Identifier } from "../implementation/expression/identifier"; -import { MemberAccess } from "../implementation/expression/member_access"; -import { IdentifierPath } from "../implementation/meta/identifier_path"; -import { UserDefinedTypeName } from "../implementation/type/user_defined_type_name"; -import { BuiltinReferencedDeclarationNormalizer } from "./builtin_referenced_declaration_normalizer"; -import { StructuredDocumentationReconstructingPostprocessor } from "./structured_documentation_reconstruction"; - -const reconstructor = new StructuredDocumentationReconstructingPostprocessor(1000); -const refNormalizer = new BuiltinReferencedDeclarationNormalizer(100); - -function sortByPriority(a: ASTNodePostprocessor, b: ASTNodePostprocessor): number { - return a.priority - b.priority; -} - -export const DefaultPostprocessorMapping = new Map< - ASTNodeConstructor, - ASTNodePostprocessor[] ->([ - [ContractDefinition, [reconstructor].sort(sortByPriority)], - [EventDefinition, [reconstructor].sort(sortByPriority)], - [FunctionDefinition, [reconstructor].sort(sortByPriority)], - [ModifierDefinition, [reconstructor].sort(sortByPriority)], - [VariableDeclaration, [reconstructor].sort(sortByPriority)], - - [Identifier, [refNormalizer].sort(sortByPriority)], - [MemberAccess, [refNormalizer].sort(sortByPriority)], - [IdentifierPath, [refNormalizer].sort(sortByPriority)], - [UserDefinedTypeName, [refNormalizer].sort(sortByPriority)] -]); diff --git a/src/ast/postprocessing/node_postprocessor.ts b/src/ast/postprocessing/node_postprocessor.ts index 36f24856..63392fc7 100644 --- a/src/ast/postprocessing/node_postprocessor.ts +++ b/src/ast/postprocessing/node_postprocessor.ts @@ -1,12 +1,13 @@ import { ASTNode } from "../ast_node"; import { ASTContext, ASTNodePostprocessor } from "../ast_reader"; -export abstract class NodePostprocessor implements ASTNodePostprocessor { +export abstract class NodePostprocessor implements ASTNodePostprocessor { readonly priority: number; constructor(priority: number) { this.priority = priority; } - abstract process(node: ASTNode, context: ASTContext, sources?: Map): void; + abstract process(node: T, context: ASTContext, sources?: Map): void; + abstract isSupportedNode(node: ASTNode): node is T; } diff --git a/src/ast/postprocessing/structured_documentation_reconstruction.ts b/src/ast/postprocessing/structured_documentation_reconstruction.ts index ce4f411f..9bed3f15 100644 --- a/src/ast/postprocessing/structured_documentation_reconstruction.ts +++ b/src/ast/postprocessing/structured_documentation_reconstruction.ts @@ -127,14 +127,10 @@ type SupportedNode = | EventDefinition | ModifierDefinition; -export class StructuredDocumentationReconstructingPostprocessor extends NodePostprocessor { +export class StructuredDocumentationReconstructingPostprocessor extends NodePostprocessor { private reconstructor = new StructuredDocumentationReconstructor(); - process(node: ASTNode, context: ASTContext, sources?: Map): void { - if (!this.isSupportedNode(node)) { - return; - } - + process(node: SupportedNode, context: ASTContext, sources?: Map): void { if (node.documentation instanceof StructuredDocumentation || sources === undefined) { return; } @@ -161,7 +157,7 @@ export class StructuredDocumentationReconstructingPostprocessor extends NodePost structDocNode.parent = node; } - private isSupportedNode(node: ASTNode): node is SupportedNode { + isSupportedNode(node: ASTNode): node is SupportedNode { return ( node instanceof FunctionDefinition || node instanceof ContractDefinition || From e895e0a57a1df4a5102bbd6ac1e2efe77a1df9d2 Mon Sep 17 00:00:00 2001 From: blitz-1306 Date: Wed, 25 Aug 2021 13:48:22 +0500 Subject: [PATCH 4/4] Removed priority in node postprocessors as it is not really needed there --- src/ast/ast_reader.ts | 19 ++++--------------- ...iltin_referenced_declaration_normalizer.ts | 5 ++--- src/ast/postprocessing/index.ts | 1 - src/ast/postprocessing/list.ts | 8 +++----- src/ast/postprocessing/node_postprocessor.ts | 13 ------------- ...structured_documentation_reconstruction.ts | 7 ++++--- 6 files changed, 13 insertions(+), 40 deletions(-) delete mode 100644 src/ast/postprocessing/node_postprocessor.ts diff --git a/src/ast/ast_reader.ts b/src/ast/ast_reader.ts index 5265ea12..3a51d424 100644 --- a/src/ast/ast_reader.ts +++ b/src/ast/ast_reader.ts @@ -14,8 +14,6 @@ export interface ASTNodeProcessor { } export interface ASTNodePostprocessor { - readonly priority: number; - process(node: T, context: ASTContext, sources?: Map): void; isSupportedNode(node: ASTNode): node is T; } @@ -123,10 +121,10 @@ export class ASTContext { } export class ASTPostprocessor { - nodePostprocessors: ReadonlyArray>; + nodePostprocessors: Array>; constructor(nodePostProcessors = DefaultNodePostprocessorList) { - this.nodePostprocessors = nodePostProcessors.sort((a, b) => b.priority - a.priority); + this.nodePostprocessors = nodePostProcessors; } getPostprocessorsForNode(node: ASTNode): Array> { @@ -144,22 +142,13 @@ export class ASTPostprocessor { } processContext(context: ASTContext, sources?: Map): void { - const groups: Array<[ASTNodePostprocessor, ASTNode[]]> = - this.nodePostprocessors.map((postprocessor) => [postprocessor, []]); - - for (const [postprocessor, nodes] of groups) { + for (const postprocessor of this.nodePostprocessors) { for (const node of context.nodes) { if (postprocessor.isSupportedNode(node)) { - nodes.push(node); + postprocessor.process(node, context, sources); } } } - - for (const [postprocessor, nodes] of groups) { - for (const node of nodes) { - postprocessor.process(node, context, sources); - } - } } } diff --git a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts index fa8430bb..7d03e24e 100644 --- a/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts +++ b/src/ast/postprocessing/builtin_referenced_declaration_normalizer.ts @@ -1,14 +1,13 @@ import { ASTNode } from "../ast_node"; -import { ASTContext } from "../ast_reader"; +import { ASTContext, ASTNodePostprocessor } from "../ast_reader"; import { Identifier } from "../implementation/expression/identifier"; import { MemberAccess } from "../implementation/expression/member_access"; import { IdentifierPath } from "../implementation/meta/identifier_path"; import { UserDefinedTypeName } from "../implementation/type/user_defined_type_name"; -import { NodePostprocessor } from "./node_postprocessor"; type SupportedNode = Identifier | MemberAccess | IdentifierPath | UserDefinedTypeName; -export class BuiltinReferencedDeclarationNormalizer extends NodePostprocessor { +export class BuiltinReferencedDeclarationNormalizer implements ASTNodePostprocessor { process(node: SupportedNode, context: ASTContext): void { if ( node.referencedDeclaration >= 0 && diff --git a/src/ast/postprocessing/index.ts b/src/ast/postprocessing/index.ts index 432b922a..106203e4 100644 --- a/src/ast/postprocessing/index.ts +++ b/src/ast/postprocessing/index.ts @@ -1,4 +1,3 @@ export * from "./builtin_referenced_declaration_normalizer"; export * from "./list"; -export * from "./node_postprocessor"; export * from "./structured_documentation_reconstruction"; diff --git a/src/ast/postprocessing/list.ts b/src/ast/postprocessing/list.ts index d173056a..b04cab74 100644 --- a/src/ast/postprocessing/list.ts +++ b/src/ast/postprocessing/list.ts @@ -4,11 +4,9 @@ import { BuiltinReferencedDeclarationNormalizer } from "./builtin_referenced_dec import { StructuredDocumentationReconstructingPostprocessor } from "./structured_documentation_reconstruction"; /** - * Higher priority value means earlier execution. - * Do not use same priority values for different node postprocessors - * (may result unpredictable behavior). + * Note that order here really matters */ export const DefaultNodePostprocessorList: Array> = [ - new BuiltinReferencedDeclarationNormalizer(1000), - new StructuredDocumentationReconstructingPostprocessor(100) + new BuiltinReferencedDeclarationNormalizer(), + new StructuredDocumentationReconstructingPostprocessor() ]; diff --git a/src/ast/postprocessing/node_postprocessor.ts b/src/ast/postprocessing/node_postprocessor.ts deleted file mode 100644 index 63392fc7..00000000 --- a/src/ast/postprocessing/node_postprocessor.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ASTNode } from "../ast_node"; -import { ASTContext, ASTNodePostprocessor } from "../ast_reader"; - -export abstract class NodePostprocessor implements ASTNodePostprocessor { - readonly priority: number; - - constructor(priority: number) { - this.priority = priority; - } - - abstract process(node: T, context: ASTContext, sources?: Map): void; - abstract isSupportedNode(node: ASTNode): node is T; -} diff --git a/src/ast/postprocessing/structured_documentation_reconstruction.ts b/src/ast/postprocessing/structured_documentation_reconstruction.ts index 9bed3f15..7f8418c3 100644 --- a/src/ast/postprocessing/structured_documentation_reconstruction.ts +++ b/src/ast/postprocessing/structured_documentation_reconstruction.ts @@ -1,5 +1,5 @@ import { ASTNode } from "../ast_node"; -import { ASTContext } from "../ast_reader"; +import { ASTContext, ASTNodePostprocessor } from "../ast_reader"; import { ContractDefinition, ErrorDefinition, @@ -10,7 +10,6 @@ import { } from "../implementation/declaration"; import { SourceUnit } from "../implementation/meta/source_unit"; import { StructuredDocumentation } from "../implementation/meta/structured_documentation"; -import { NodePostprocessor } from "./node_postprocessor"; export class StructuredDocumentationReconstructor { process(node: ASTNode, source: string): StructuredDocumentation | undefined { @@ -127,7 +126,9 @@ type SupportedNode = | EventDefinition | ModifierDefinition; -export class StructuredDocumentationReconstructingPostprocessor extends NodePostprocessor { +export class StructuredDocumentationReconstructingPostprocessor + implements ASTNodePostprocessor +{ private reconstructor = new StructuredDocumentationReconstructor(); process(node: SupportedNode, context: ASTContext, sources?: Map): void {