Skip to content

Commit

Permalink
feat: diagnostic for hardhat error 411 - library not installed
Browse files Browse the repository at this point in the history
  • Loading branch information
antico5 committed Sep 8, 2022
1 parent b0d1667 commit 44ba952
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 47 deletions.
64 changes: 41 additions & 23 deletions server/src/services/validation/convertHardhatErrorToDiagnostic.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,57 @@
import { Diagnostic, DiagnosticSeverity, Range } from "@common/types";
import { TextDocument } from "vscode-languageserver-textdocument";
import type { HardhatError, HardhatImportLineError } from "../../types";
import type {
HardhatError,
HardhatImportFileError,
HardhatImportLibraryError,
} from "../../types";

export const IMPORT_LINE_ERROR_CODES = [404, 405, 406, 407, 408, 409];
export const IMPORT_FILE_ERROR_CODES = [404, 405, 406, 407, 408, 409];
export const IMPORT_LIBRARY_ERROR_CODES = [411];

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isHardhatImportLineError(error: any): error is HardhatImportLineError {
if (error.errorDescriptor === undefined) {
return false;
}
function isHardhatImportFileError(
error: HardhatError
): error is HardhatImportFileError {
const errorCode = error?.errorDescriptor?.number;

return IMPORT_FILE_ERROR_CODES.includes(errorCode);
}

const errorCode = error.errorDescriptor.number;
function isHardhatImportLibraryError(
error: HardhatError
): error is HardhatImportLibraryError {
const errorCode = error?.errorDescriptor?.number;

return IMPORT_LINE_ERROR_CODES.includes(errorCode);
return IMPORT_LIBRARY_ERROR_CODES.includes(errorCode);
}

function getImportString(err: HardhatError) {
if (isHardhatImportFileError(err)) {
return err.messageArguments.imported;
} else if (isHardhatImportLibraryError(err)) {
return err.messageArguments.library;
} else {
return null;
}
}

export function convertHardhatErrorToDiagnostic(
document: TextDocument,
err: HardhatError
): Diagnostic | null {
if (!isHardhatImportLineError(err)) {
return null;
}
const importString = getImportString(err);

return resolveImportLineError(document, err, err.errorDescriptor.title);
if (importString === null) return null;

return resolveImportError(document, err, importString);
}

function resolveImportLineError(
function resolveImportError(
document: TextDocument,
err: HardhatImportLineError,
message: string
err: HardhatError,
importString: string
) {
const range = findRangeForImport(document, err);
const range = findRangeForImport(document, importString);

if (!range) {
return null;
Expand All @@ -41,24 +61,22 @@ function resolveImportLineError(
severity: DiagnosticSeverity.Error,
code: err.errorDescriptor.number,
source: "hardhat",
message,
message: err.errorDescriptor.title,
range,
};
}

function findRangeForImport(
document: TextDocument,
err: HardhatImportLineError
importString: string
): Range | null {
const imported = err.messageArguments.imported;

const startIndex = document.getText().indexOf(imported);
const startIndex = document.getText().indexOf(importString);

if (startIndex === -1) {
return null;
}

const endIndex = startIndex + imported.length;
const endIndex = startIndex + importString.length;

return {
start: document.positionAt(startIndex),
Expand Down
35 changes: 13 additions & 22 deletions server/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,26 @@ export interface WorkerState {
logger: WorkerLogger;
}

export type ImportLineErrorCode = 404 | 405 | 406 | 407 | 408 | 409;
export interface HardhatImportFileError extends HardhatError {
messageArguments: {
imported: string;
};
}

export interface HardhatImportLineError {
name: "HardhatError";
errorDescriptor: {
number: number;
message: string;
title: string;
description: string;
shouldBeReported: boolean;
export interface HardhatImportLibraryError extends HardhatError {
messageArguments: {
library: string;
};
}

export interface HardhatSourceImportError extends HardhatError {
messageArguments: {
imported: string;
from: string;
};
}

export interface UnknownHardhatError {
export interface HardhatError {
name: "HardhatError";
errorDescriptor: {
number: number;
Expand All @@ -187,18 +190,6 @@ export interface UnknownHardhatError {
messageArguments?: unknown;
}

export interface HardhatSourceImportError extends UnknownHardhatError {
messageArguments: {
imported: string;
from: string;
};
}

export type HardhatError =
| UnknownHardhatError
| HardhatImportLineError
| HardhatSourceImportError;

export interface ValidateCommand {
type: "VALIDATE";
jobId: number;
Expand Down
41 changes: 39 additions & 2 deletions server/test/services/validation/convertHardhatErrorToDiagnostic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import {
Diagnostic,
Range,
} from "@common/types";
import { convertHardhatErrorToDiagnostic } from "@services/validation/convertHardhatErrorToDiagnostic";
import {
convertHardhatErrorToDiagnostic,
IMPORT_FILE_ERROR_CODES,
IMPORT_LIBRARY_ERROR_CODES,
} from "@services/validation/convertHardhatErrorToDiagnostic";
import { assert } from "chai";

interface ErrorDescription {
Expand Down Expand Up @@ -173,6 +177,32 @@ Hardhat's compiler is case sensitive to ensure projects are portable across diff
});
});

describe("411 - Invalid import: missing library", () => {
it("should convert to a diagnostic", () => {
const errorDescription =
"A Solidity file is trying to import another which belongs to a library that is not installed.\n \nTry installing the library using npm.";

assertConversionToDiagnostic(
"@foo/Bar.sol",
{
number: 411,
message:
"The library %library%, imported from %from%, is not installed. Try installing it using npm.",
title: "Invalid import: library not installed",
description: errorDescription,
shouldBeReported: false,
},
{
message: "Invalid import: library not installed",
range: {
start: { line: 0, character: 8 },
end: { line: 0, character: 20 },
},
}
);
});
});

describe("unhandled - an unknown hardhat error", () => {
const fileText = `
//SPDX-License-Identifier: Unlicense
Expand Down Expand Up @@ -285,12 +315,19 @@ function assertConversionToDiagnostic(

const document = TextDocument.create(exampleUri, "solidity", 0, fileText);

let messageArguments = {};
if (IMPORT_FILE_ERROR_CODES.includes(errorDescription.number)) {
messageArguments = { imported: importLine };
} else if (IMPORT_LIBRARY_ERROR_CODES.includes(errorDescription.number)) {
messageArguments = { library: importLine };
}

const diagnostic: Diagnostic | null = convertHardhatErrorToDiagnostic(
document,
{
name: "HardhatError",
errorDescriptor: errorDescription,
messageArguments: { imported: importLine },
messageArguments,
}
);

Expand Down

0 comments on commit 44ba952

Please sign in to comment.