Skip to content

Commit

Permalink
feat(ir): Import Graph (nowarp#180)
Browse files Browse the repository at this point in the history
* feat(idx): Generate unique idx for each element

* chore(cli): Refactor

* fix(dumpCfg): Options description

* feat(imports): Initial version of imports graph

Closes nowarp#60

* fix(changelog)

* chore(changelog): Update

* chore: Update expected outputs of `tactIR.spec.t`

* feat(imports): Improve stdlib handling

* fix(warnings): Path in warnings for multi-contracts configs

* feat(dumpImports): Improve coloring
  • Loading branch information
jubnzv authored Oct 17, 2024
1 parent 3451f86 commit 5668d62
Show file tree
Hide file tree
Showing 100 changed files with 4,235 additions and 3,216 deletions.
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- `SendInLoop` detector: PR [#168](https://github.com/nowarp/misti/pulls/168)
- `CellOverflow` detector: PR [#177](https://github.com/nowarp/misti/pulls/177)
- Import Graph: PR [#180](https://github.com/nowarp/misti/pulls/180)

## [0.4.2] - 2024-10-12

### Fixed
Expand All @@ -22,10 +27,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.4.0] - 2024-10-08

### Added
- `SendInLoop` detector: PR [#168](https://github.com/nowarp/misti/pulls/168)
- `CellOverflow` detector: PR [#177](https://github.com/nowarp/misti/pulls/177)

### Added
- `OptimalMathFunction` detector: Issue [#146](https://github.com/nowarp/misti/issues/146)
- `DuplicatedCondition` detector: Issue [#147](https://github.com/nowarp/misti/issues/147)
Expand Down
26 changes: 18 additions & 8 deletions src/cli/driver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CLIOptions, cliOptionDefaults } from "./options";
import { MistiTactPath } from "./path";
import {
MistiResult,
ToolOutput,
Expand Down Expand Up @@ -41,22 +42,31 @@ export class Driver {
singleContractProjectManager: SingleContractProjectManager | undefined;

private constructor(tactPath: string | undefined, options: CLIOptions) {
let mistiTactPath: MistiTactPath | undefined;
if (tactPath) {
const singleContract = tactPath.endsWith(".tact");
if (!fs.existsSync(tactPath)) {
throw ExecutionException.make(
`${singleContract ? "Contract" : "Project"} ${tactPath} is not available.`,
);
}
this.tactConfigPath = singleContract
? (() => {
this.singleContractProjectManager =
SingleContractProjectManager.fromContractPath(tactPath);
return this.singleContractProjectManager.createTempProjectDir();
})()
: path.resolve(tactPath); // Tact supports absolute paths only
if (singleContract) {
this.singleContractProjectManager =
SingleContractProjectManager.fromContractPath(tactPath);
this.tactConfigPath =
this.singleContractProjectManager.createTempProjectDir();
mistiTactPath = {
kind: "contract",
tempConfigPath: path.resolve(this.tactConfigPath),
originalPath: path.resolve(tactPath),
};
} else {
// Tact supports absolute paths only
this.tactConfigPath = path.resolve(tactPath);
mistiTactPath = { kind: "config", path: path.resolve(tactPath) };
}
}
this.ctx = new MistiContext(tactPath, options);
this.ctx = new MistiContext(mistiTactPath, options);
this.disabledDetectors = new Set(options.disabledDetectors ?? []);
this.colorizeOutput = options.colors;
this.minSeverity = options.minSeverity;
Expand Down
1 change: 1 addition & 0 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from "./driver";
export * from "./result";
export * from "./types";
export * from "./options";
export * from "./path";
export * from "./cli";
5 changes: 4 additions & 1 deletion src/cli/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ export const cliOptions = [
.default(cliOptionDefaults.tools),
new Option(
"--output-path <PATH>",
"Directory to save warnings or output generated by tools. If <PATH> is '-', then stdout is used.",
[
"Directory to save warnings or output generated by tools.",
`If <PATH> is ${STDOUT_PATH}, then stdout is used.`,
].join(" "),
).default(cliOptionDefaults.outputPath),
new Option("--list-tools", "List available tools and their options.").default(
cliOptionDefaults.listTools,
Expand Down
60 changes: 60 additions & 0 deletions src/cli/path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { unreachable } from "../internals/util";
import path from "path";

/**
* Path to a Tact contract or configuration provided by the user.
*/
export type MistiTactPath =
| {
kind: "config";
/**
* Absolute path to the tact.config.json.
*/
path: string;
}
| {
kind: "contract";
/**
* A path to a temporary configuration file generated internally in Misti (absolute).
*/
tempConfigPath: string;
/**
* A path to the contract as it was specified by the user (absolute).
*/
originalPath: string;
};

/**
* Returns path to a contract or configuration file as it is provided by the user.
*/
export function getOriginalPath(path: MistiTactPath): string {
switch (path.kind) {
case "config":
return path.path;
case "contract":
return path.originalPath;
default:
unreachable(path);
}
}

/**
* Returns an actual path to a configuration file used in Misti.
*/
export function getActualPath(path: MistiTactPath): string {
switch (path.kind) {
case "config":
return path.path;
case "contract":
return path.tempConfigPath;
default:
unreachable(path);
}
}

/**
* Returns an absolute path to an actual project directory used by Misti.
*/
export function getProjectDirectory(tactPath: MistiTactPath): string {
return path.dirname(getActualPath(tactPath));
}
38 changes: 31 additions & 7 deletions src/internals/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,36 @@ import { MistiConfig } from "./config";
import { DebugLogger, Logger, QuietLogger, TraceLogger } from "./logger";
import { CLIOptions, cliOptionDefaults } from "../cli";
import { throwZodError } from "./exceptions";
import { TactConfigManager } from "./tact/config";
import { MistiTactPath, getActualPath, getProjectDirectory } from "../cli/path";
import { execSync } from "child_process";
import path from "path";

/**
* Represents the context for a Misti run.
*/
export class MistiContext {
logger: Logger;
config: MistiConfig;
/** Indicates whether a Souffle binary is available. */

/**
* Indicates whether a Souffle binary is available.
*/
readonly souffleAvailable: boolean;
/** Path to a single Tact contract if executed without project config. */
readonly singleContractPath: string | undefined;

/**
* Path to the Tact contract/configuration provided by the user.
*/
readonly tactPath: MistiTactPath | undefined;

/**
* Initializes the context for Misti, setting up configuration and appropriate logger.
*/
constructor(
tactPath: string | undefined,
tactPath: MistiTactPath | undefined,
options: CLIOptions = cliOptionDefaults,
) {
this.singleContractPath = tactPath?.endsWith(".tact")
? tactPath
: undefined;
this.tactPath = tactPath;
this.souffleAvailable = this.checkSouffleInstallation(
options.souffleBinary,
);
Expand Down Expand Up @@ -77,4 +84,21 @@ export class MistiContext {
return false;
}
}

/**
* Returns entry points taking into account the user's configuration.
*
* @returns Absolute paths to entrypoint files.
*/
public getEntryPoints(): string[] {
if (this.tactPath === undefined) {
return [];
}
const configPath = getActualPath(this.tactPath);
const projectDir = getProjectDirectory(this.tactPath);
const configManager = new TactConfigManager(this, configPath);
return configManager.config.projects.map((project) =>
path.resolve(projectDir, project.path),
);
}
}
2 changes: 1 addition & 1 deletion src/internals/ir/builders/astStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TactASTStore } from "..";
import { definedInStdlib } from "./tactStdlib";
import { MistiContext } from "../../context";
import { definedInStdlib } from "../../tact/stdlib";
import { unreachable } from "../../util";
import {
AstAsmFunctionDef,
Expand Down
Loading

0 comments on commit 5668d62

Please sign in to comment.