Skip to content

Commit

Permalink
refactor: eliminate the parser
Browse files Browse the repository at this point in the history
  • Loading branch information
gas1cent committed Jan 12, 2024
1 parent 18c8854 commit ca848d5
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 78 deletions.
50 changes: 0 additions & 50 deletions src/parser.ts

This file was deleted.

6 changes: 2 additions & 4 deletions src/processor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import fs from 'fs';
import { Parser } from './parser';
import { Config } from './types/config.t';
import { Validator } from './validator';
import { SourceUnit, FunctionDefinition, ContractDefinition } from 'solc-typed-ast';
import { NodeToProcess } from './types/solc-typed-ast.t';
import { parseNodeNatspec } from './utils';

interface IWarning {
location: string;
Expand All @@ -13,12 +13,10 @@ interface IWarning {
export class Processor {
config: Config;
validator: Validator;
parser: Parser;

constructor(config: Config) {
this.config = config;
this.validator = new Validator(config);
this.parser = new Parser();
}

processSources(sourceUnits: SourceUnit[]): IWarning[] {
Expand All @@ -42,7 +40,7 @@ export class Processor {
}

validateNatspec(node: NodeToProcess): string[] {
const nodeNatspec = this.parser.parseNodeNatspec(node);
const nodeNatspec = parseNodeNatspec(node);
return this.validator.validate(node, nodeNatspec);
}

Expand Down
48 changes: 48 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import fs from 'fs/promises';
import path from 'path';
import { ASTKind, ASTReader, SourceUnit, compileSol } from 'solc-typed-ast';
import { Natspec, NatspecDefinition } from './types/natspec.t';
import { NodeToProcess } from './types/solc-typed-ast.t';

export async function getProjectCompiledSources(rootPath: string, contractsPath: string, ignoredPaths: string[]): Promise<SourceUnit[]> {
// Fetch Solidity files from the specified directory
Expand Down Expand Up @@ -62,3 +64,49 @@ export async function getRemappings(rootPath: string): Promise<string[]> {
return [];
}
}

export function parseNodeNatspec(node: NodeToProcess): Natspec {
if (!node.documentation) {
return { tags: [], params: [], returns: [] };
}

let currentTag: NatspecDefinition | null = null;
const result: Natspec = {
tags: [],
params: [],
returns: [],
};

const docText: string = typeof node.documentation === 'string' ? node.documentation : node.documentation.text;

docText.split('\n').forEach((line) => {
const tagTypeMatch = line.match(/^\s*@(\w+)/);
if (tagTypeMatch) {
const tagName = tagTypeMatch[1];

if (tagName === 'inheritdoc') {
const tagMatch = line.match(/^\s*@(\w+) (.*)$/);
if (tagMatch) {
currentTag = null;
result.inheritdoc = { content: tagMatch[2] };
}
} else if (tagName === 'param' || tagName === 'return') {
const tagMatch = line.match(/^\s*@(\w+) *(\w+) (.*)$/);
if (tagMatch) {
currentTag = { name: tagMatch[2], content: tagMatch[3].trim() };
result[tagName === 'param' ? 'params' : 'returns'].push(currentTag);
}
} else {
const tagMatch = line.match(/^\s*@(\w+) *(.*)$/);
if (tagMatch) {
currentTag = { name: tagName, content: tagMatch[2] };
result.tags.push(currentTag);
}
}
} else if (currentTag) {
currentTag.content += '\n' + line;
}
});

return result;
}
47 changes: 23 additions & 24 deletions test/parser.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { ContractDefinition } from 'solc-typed-ast';
import { Parser } from '../src/parser';
import { getFileCompiledSource } from './utils';
import { parseNodeNatspec } from '../src/utils';
import { mockNatspec } from './mocks';

describe('Parser', () => {
const parser: Parser = new Parser();
let contract: ContractDefinition;

describe('Contract', () => {
Expand All @@ -15,7 +14,7 @@ describe('Parser', () => {

it('should parse the inheritdoc tag', async () => {
const node = contract.vFunctions.find(({ name }) => name === 'viewFunctionNoParams')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -32,7 +31,7 @@ describe('Parser', () => {

it('should parse constant', async () => {
const node = contract.vStateVariables.find(({ name }) => name === 'SOME_CONSTANT')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -45,7 +44,7 @@ describe('Parser', () => {

it('should parse variable', async () => {
const node = contract.vStateVariables.find(({ name }) => name === 'someVariable')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -58,7 +57,7 @@ describe('Parser', () => {

it('should parse modifier', async () => {
const node = contract.vModifiers.find(({ name }) => name === 'someModifier')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -80,7 +79,7 @@ describe('Parser', () => {

it('should parse external function', async () => {
const node = contract.vFunctions.find(({ name }) => name === 'viewFunctionNoParams')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -99,7 +98,7 @@ describe('Parser', () => {

it('should parse private function', async () => {
const node = contract.vFunctions.find(({ name }) => name === '_viewPrivate')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand Down Expand Up @@ -131,7 +130,7 @@ describe('Parser', () => {

it('should parse multiline descriptions', async () => {
const node = contract.vFunctions.find(({ name }) => name === '_viewMultiline')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -147,7 +146,7 @@ describe('Parser', () => {

it('should parse multiple of the same tag', async () => {
const node = contract.vFunctions.find(({ name }) => name === '_viewDuplicateTag')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -174,7 +173,7 @@ describe('Parser', () => {

it('should parse error', async () => {
const node = contract.vErrors.find(({ name }) => name === 'SimpleError')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -190,7 +189,7 @@ describe('Parser', () => {

it('should parse event', async () => {
const node = contract.vEvents.find(({ name }) => name === 'SimpleEvent')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -206,7 +205,7 @@ describe('Parser', () => {

it('should parse struct', async () => {
const node = contract.vStructs.find(({ name }) => name === 'SimplestStruct')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand Down Expand Up @@ -235,7 +234,7 @@ describe('Parser', () => {
// TODO: Parse natspec for enums
// it('should parse enum', async () => {
// const node = contract.vEnums.find(({ name }) => name === 'SimpleEnum')!;
// const result = parser.parseNodeNatspec(node);
// const result = parseNodeNatspec(node);

// expect(result).toEqual(mockNatspec({
// tags: [],
Expand All @@ -244,7 +243,7 @@ describe('Parser', () => {

it('should parse external function without parameters', async () => {
const node = contract.vFunctions.find(({ name }) => name === 'viewFunctionNoParams')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -270,7 +269,7 @@ describe('Parser', () => {

it('should parse external function with parameters', async () => {
const node = contract.vFunctions.find(({ name }) => name === 'viewFunctionWithParams')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand Down Expand Up @@ -309,7 +308,7 @@ describe('Parser', () => {

it('should parse struct', async () => {
const node = contract.vStructs.find(({ name }) => name === 'SimpleStruct')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -320,7 +319,7 @@ describe('Parser', () => {

it('should parse inheritdoc + natspec', async () => {
const node = contract.vStateVariables.find(({ name }) => name === 'someVariable')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -339,21 +338,21 @@ describe('Parser', () => {

it('should not parse the inheritdoc tag with just 2 slashes', async () => {
const node = contract.vStateVariables.find(({ name }) => name === 'SOME_CONSTANT')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(mockNatspec({}));
});

it('should not parse regular comments as natspec', async () => {
const node = contract.vFunctions.find(({ name }) => name === 'viewFunctionWithParams')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(mockNatspec({}));
});

it('should parse natspec with multiple spaces', async () => {
const node = contract.vFunctions.find(({ name }) => name === '_viewPrivate')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand Down Expand Up @@ -381,14 +380,14 @@ describe('Parser', () => {

it('should not parse natspec with invalid number of slashes', async () => {
const node = contract.vFunctions.find(({ name }) => name === '_viewInternal')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(mockNatspec({}));
});

it('should parse block natspec with invalid formatting', async () => {
const node = contract.vFunctions.find(({ name }) => name === '_viewBlockLinterFail')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand All @@ -404,7 +403,7 @@ describe('Parser', () => {

it('should parse block natspec with invalid formatting', async () => {
const node = contract.vFunctions.find(({ name }) => name === '_viewLinterFail')!;
const result = parser.parseNodeNatspec(node);
const result = parseNodeNatspec(node);

expect(result).toEqual(
mockNatspec({
Expand Down

0 comments on commit ca848d5

Please sign in to comment.