Skip to content

Commit

Permalink
feat(sol-0.8): add support for export of function at root level
Browse files Browse the repository at this point in the history
  • Loading branch information
RyuuGan committed Feb 7, 2022
1 parent 63487f3 commit 7a9e2db
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 4 deletions.
26 changes: 26 additions & 0 deletions lib/antlr/visitors/exportVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ContractDefinitionContext,
EnumDefinitionContext,
ErrorDefinitionContext,
FunctionDefinitionContext,
InheritanceSpecifierListContext,
InterfaceDefinitionContext,
LibraryDefinitionContext,
Expand Down Expand Up @@ -372,4 +373,29 @@ class ExportVisitor implements SolidityParserListener {
typeName: typeName.text,
});
}

enterFunctionDefinition(ctx: FunctionDefinitionContext): void {
if (!(ctx.parent instanceof SourceUnitContext)) {
return;
}

if (!ctx.stop) {
return;
}

const start = ctx.start.startIndex;
const end = ctx.stop.stopIndex;
const name = ctx.identifier();

if (!name?.stop) {
return;
}

this.#onVisit({
type: ExportType.function,
start,
end,
name: name.text,
});
}
}
8 changes: 7 additions & 1 deletion lib/antlr/visitors/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export interface ImportVisitNamedImport {

export type ExportVisitResult =
| ExportVisitResultContractLike
| ExportVisitResultConstant;
| ExportVisitResultConstant
| ExportVisitResultFunction;

export interface ExportVisitResultContractLike extends RangeVisitResult {
abstract: boolean;
Expand All @@ -35,4 +36,9 @@ export interface ExportVisitResultConstant extends RangeVisitResult {
name: string;
}

export interface ExportVisitResultFunction extends RangeVisitResult {
type: ExportType.function;
name: string;
}

export type VisitCallback<T extends RangeVisitResult> = (v: T) => void;
30 changes: 28 additions & 2 deletions lib/exportsAnalyzer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import Debug from 'debug';
import { SolidityExportVisitor } from './antlr/visitors/exportVisitor';
import { ExportVisitResultConstant } from './antlr/visitors/types';
import {
ExportVisitResultConstant,
ExportVisitResultFunction,
} from './antlr/visitors/types';
import { ContractLikeExportType, ExportType } from './types';

const error = Debug('sol-merger:error');

export type ExportsAnalyzerResult =
| ExportsAnalyzerResultContractLike
| ExportsAnalyzerResultConstant;
| ExportsAnalyzerResultConstant
| ExportsAnalyzerResultFunction;

export interface ExportsAnalyzerResultContractLike {
abstract: boolean;
Expand All @@ -24,6 +28,12 @@ export interface ExportsAnalyzerResultConstant {
typeName: string;
}

export interface ExportsAnalyzerResultFunction {
type: ExportType.function;
name: string;
body: string;
}

export class ExportsAnalyzer {
constructor(private contents: string) {}

Expand All @@ -47,6 +57,12 @@ export class ExportsAnalyzer {
results.push(constantExport);
return;
}

if (e.type === ExportType.function) {
const functionExport = this.analyzeExportFunction(e);
results.push(functionExport);
return;
}
results.push({
abstract: e.abstract,
type: e.type,
Expand Down Expand Up @@ -74,4 +90,14 @@ export class ExportsAnalyzer {
typeName: e.typeName,
};
}

private analyzeExportFunction(
e: ExportVisitResultFunction,
): ExportsAnalyzerResultFunction {
return {
body: this.contents.substring(e.start, e.end + 1),
name: e.name,
type: ExportType.function,
};
}
}
4 changes: 4 additions & 0 deletions lib/fileAnalyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class FileAnalyzer {
return `${e.typeName} ${e.type} ${e.name}${e.body}`;
}

if (e.type === ExportType.function) {
return e.body;
}

let is = e.is;
if (is) {
globalRenames.forEach((i) => {
Expand Down
3 changes: 2 additions & 1 deletion lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ export enum ExportType {
error = 'error',
constant = 'constant',
function = 'function',
userDefinedValueType = 'userDefinedValueType',
}

export type ContractLikeExportType = Exclude<
ExportType,
ExportType.constant | ExportType.function
ExportType.constant | ExportType.function | ExportType.userDefinedValueType
>;

export interface ExportPluginProcessor {
Expand Down
19 changes: 19 additions & 0 deletions test/compiled/ContractWithTopLevelFunction.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity >=0.7.1 <0.9.0;


// SPDX-License-Identifier: GPL-3.0
function sum(uint[] memory _arr) pure returns (uint s) {
for (uint i = 0; i < _arr.length; i++)
s += _arr[i];
}

contract ArrayExample {
bool found;
function f(uint[] memory _arr) public {
// This calls the free function internally.
// The compiler will add its code to the contract.
uint s = sum(_arr);
require(s >= 10);
found = true;
}
}
18 changes: 18 additions & 0 deletions test/contracts/ContractWithTopLevelFunction.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.1 <0.9.0;

function sum(uint[] memory _arr) pure returns (uint s) {
for (uint i = 0; i < _arr.length; i++)
s += _arr[i];
}

contract ArrayExample {
bool found;
function f(uint[] memory _arr) public {
// This calls the free function internally.
// The compiler will add its code to the contract.
uint s = sum(_arr);
require(s >= 10);
found = true;
}
}
22 changes: 22 additions & 0 deletions test/exportsAnalyzer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,27 @@ describe('ExportsAnalyzer', () => {

assert.deepEqual(exports, []);
});

it('should analyze function export', () => {
const exportsAnalyzer = new ExportsAnalyzer(`
function sum(uint[] memory _arr) pure returns (uint s) {
for (uint i = 0; i < _arr.length; i++)
s += _arr[i];
}
`);

const exports = exportsAnalyzer.analyzeExports();

assert.deepEqual(exports, [
{
name: 'sum',
type: ExportType.function,
body: `function sum(uint[] memory _arr) pure returns (uint s) {
for (uint i = 0; i < _arr.length; i++)
s += _arr[i];
}`,
},
]);
});
});
});
4 changes: 4 additions & 0 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,8 @@ describe('Solidity Merger', () => {
it('should compile file with constants at root level (0.8 support)', async () => {
await testFile('ContractWithConstants');
});

it('should compile file with functions at root level (0.8 support)', async () => {
await testFile('ContractWithTopLevelFunction');
});
});

0 comments on commit 7a9e2db

Please sign in to comment.