Skip to content

Commit

Permalink
feat: show config file
Browse files Browse the repository at this point in the history
Against each solidity file, we show a language status item that displays
the `hardhat.config.{ts/js}` file that is being used for validation.

If there is no hardhat project we show a warning message.

Fixes #56.
  • Loading branch information
kanej committed Apr 12, 2022
1 parent b155a05 commit db8956c
Show file tree
Hide file tree
Showing 16 changed files with 259 additions and 12 deletions.
6 changes: 3 additions & 3 deletions client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ export function activate(context: ExtensionContext) {
logger.info("Hardhat for Visual Studio Code Starting ...");
logger.info(`env: ${extensionState.env}`);

warnOnOtherSolidityExtensions(extensionState);
showAnalyticsAllowPopup(extensionState);

setupFormatterHook(extensionState);
setupLanguageServerHooks(extensionState);

warnOnOtherSolidityExtensions(extensionState);
showAnalyticsAllowPopup(extensionState);
}

export function deactivate(): Thenable<void> {
Expand Down
1 change: 1 addition & 0 deletions client/src/setup/setupExtensionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function setupExtensionState(
.getConfiguration("hardhat")
.get<boolean>("telemetry"),
globalTelemetryEnabled: env.isTelemetryEnabled,
hardhatConfigStatusItem: null,

telemetry,
outputChannel,
Expand Down
7 changes: 6 additions & 1 deletion client/src/setup/setupLanguageServerHooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { workspace, env } from "vscode";
import { workspace, env, window } from "vscode";
import {
LanguageClient,
LanguageClientOptions,
Expand All @@ -8,6 +8,7 @@ import {
import { ExtensionState } from "../types";
import { getUnsavedDocuments } from "../utils/getUnsavedDocuments";
import { showFileIndexingProgress } from "../popups/showFileIndexingProgress";
import { updateHardhatProjectLanguageItem } from "./updateHardhatProjectLanguageItem";

export function setupLanguageServerHooks(extensionState: ExtensionState) {
if (workspace.workspaceFolders === undefined) {
Expand Down Expand Up @@ -122,6 +123,10 @@ const startLanguageServer = (extensionState: ExtensionState): void => {
extensionState.listenerDisposables.push(telemetryChangeDisposable);
extensionState.listenerDisposables.push(hardhatTelemetryChangeDisposable);

window.onDidChangeActiveTextEditor(
updateHardhatProjectLanguageItem(extensionState)
);

client.start();

extensionState.client = client;
Expand Down
84 changes: 84 additions & 0 deletions client/src/setup/updateHardhatProjectLanguageItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { languages, Uri, LanguageStatusSeverity, TextEditor } from "vscode";
import { RequestType } from "vscode-languageclient/node";
import { ExtensionState } from "../types";

type GetSolFileDetailsParams = { uri: Uri };
type GetSolFileDetailsResponse =
| { found: false }
| { found: true; hardhat: false }
| {
found: true;
hardhat: true;
configPath: string;
configDisplayPath: string;
};

const GetSolFileDetails = new RequestType<
GetSolFileDetailsParams,
GetSolFileDetailsResponse,
void
>("solidity/getSolFileDetails");

export function updateHardhatProjectLanguageItem(
extensionState: ExtensionState
) {
return async (e: TextEditor) => {
if (e.document.languageId !== "solidity") {
return clearHardhatConfigState(extensionState);
}

const params: GetSolFileDetailsParams = { uri: e.document.uri };
const response = await extensionState.client.sendRequest(
GetSolFileDetails,
params
);

if (!response.found) {
return clearHardhatConfigState(extensionState);
}

if (extensionState.hardhatConfigStatusItem === null) {
const statusItem = languages.createLanguageStatusItem(
"hardhat-config-file",
{
language: "solidity",
}
);

extensionState.hardhatConfigStatusItem = statusItem;
}

if (response.found && !response.hardhat) {
extensionState.hardhatConfigStatusItem.severity =
LanguageStatusSeverity.Warning;
extensionState.hardhatConfigStatusItem.text =
"Not part of a Hardhat project";

extensionState.hardhatConfigStatusItem.command = null;

return;
}

if (response.found && response.hardhat) {
extensionState.hardhatConfigStatusItem.text = response.configDisplayPath;
extensionState.hardhatConfigStatusItem.command = {
title: "Open config file",
command: "vscode.open",
arguments: [response.configPath],
};

return;
}

return clearHardhatConfigState(extensionState);
};
}

function clearHardhatConfigState(extensionState: ExtensionState): void {
if (extensionState.hardhatConfigStatusItem === null) {
return;
}

extensionState.hardhatConfigStatusItem.dispose();
extensionState.hardhatConfigStatusItem = null;
}
4 changes: 3 additions & 1 deletion client/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ExtensionContext, OutputChannel } from "vscode";
import { ExtensionContext, LanguageStatusItem, OutputChannel } from "vscode";
import { Disposable, LanguageClient } from "vscode-languageclient/node";
import { Telemetry } from "./telemetry/types";
import { Logger } from "./utils/Logger";
Expand All @@ -23,4 +23,6 @@ export type ExtensionState = {
telemetry: Telemetry;
outputChannel: OutputChannel;
logger: Logger;

hardhatConfigStatusItem: LanguageStatusItem | null;
};
10 changes: 8 additions & 2 deletions server/src/parser/analyzer/HardhatProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ import { ISolProject } from "@common/types";
import { WorkspaceFolder } from "vscode-languageserver-protocol";

export class HardhatProject implements ISolProject {
basePath: string;
type: "hardhat" = "hardhat";
basePath: string;
configPath: string;
workspaceFolder: WorkspaceFolder;

constructor(basePath: string, workspaceFolder: WorkspaceFolder) {
constructor(
basePath: string,
configPath: string,
workspaceFolder: WorkspaceFolder
) {
this.basePath = basePath;
this.configPath = configPath;
this.workspaceFolder = workspaceFolder;
}
}
4 changes: 3 additions & 1 deletion server/src/parser/analyzer/NoProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { ISolProject, SolProjectType } from "@common/types";
import { WorkspaceFolder } from "vscode-languageserver-protocol";

export class NoProject implements ISolProject {
basePath: string;
type: SolProjectType = "none";
basePath: string;
configPath: string;
workspaceFolder: WorkspaceFolder;

constructor() {
this.basePath = "";
this.configPath = "";
this.workspaceFolder = {
name: "none",
uri: "",
Expand Down
6 changes: 5 additions & 1 deletion server/src/parser/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ import type {
TypeDefinition,
} from "@solidity-parser/parser/dist/src/ast-types";

import { WorkspaceFolder } from "vscode-languageserver-protocol";

import {
Position as VSCodePosition,
WorkspaceEdit,
Expand Down Expand Up @@ -359,11 +361,13 @@ export enum SolFileState {
export type SolProjectType = "hardhat" | "none";

export interface ISolProject {
type: SolProjectType;
/**
* The basepath of the solidity project.
*/
basePath: string;
type: SolProjectType;
configPath: string;
workspaceFolder: WorkspaceFolder;
}

export type SolProjectMap = {
Expand Down
60 changes: 58 additions & 2 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@ import { onReferences } from "@services/references/onReferences";
import { onImplementation } from "@services/implementation/onImplementation";
import { onRename } from "@services/rename/onRename";
import { onDidChangeContent } from "@services/validation/onDidChangeContent";
import { Uri } from "vscode";
import { RequestType } from "vscode-languageserver-protocol";
import { decodeUriAndRemoveFilePrefix } from "./utils";
import path = require("path");

export type GetSolFileDetailsParams = { uri: Uri };
export type GetSolFileDetailsResponse =
| { found: false }
| { found: true; hardhat: false }
| {
found: true;
hardhat: true;
configPath: string;
configDisplayPath: string;
};

const GetSolFileDetails = new RequestType<
GetSolFileDetailsParams,
GetSolFileDetailsResponse,
void
>("solidity/getSolFileDetails");

export default function setupServer(
connection: Connection,
Expand All @@ -35,7 +56,7 @@ export default function setupServer(

attachLanguageServerLifeCycleHooks(serverState, workspaceFileRetriever);
attachLanguageServerCommandHooks(serverState);
attachCustomNotifiactionHooks(serverState);
attachCustomHooks(serverState);

listenForDocumentChanges(serverState);

Expand Down Expand Up @@ -96,7 +117,7 @@ function attachLanguageServerCommandHooks(serverState: ServerState) {
connection.onHover(onHover(serverState));
}

function attachCustomNotifiactionHooks(serverState: ServerState) {
function attachCustomHooks(serverState: ServerState) {
const { connection, logger } = serverState;

connection.onNotification(
Expand Down Expand Up @@ -124,6 +145,41 @@ function attachCustomNotifiactionHooks(serverState: ServerState) {
serverState.hardhatTelemetryEnabled = enabled;
}
);

serverState.connection.onRequest(
GetSolFileDetails,
(params: GetSolFileDetailsParams): GetSolFileDetailsResponse => {
try {
const solFil =
serverState.solFileIndex[
decodeUriAndRemoveFilePrefix(params.uri.path)
];

if (!solFil) {
return { found: false };
}

if (solFil.project.type !== "hardhat") {
return { found: true, hardhat: false };
}

const displayConfigPath = path.relative(
decodeUriAndRemoveFilePrefix(solFil.project.workspaceFolder.uri),
solFil.project.configPath
);

return {
found: true,
hardhat: true,
configPath: solFil.project.configPath,
configDisplayPath: displayConfigPath,
};
} catch (err) {
serverState.logger.error(err);
return { found: false };
}
}
);
}

function listenForDocumentChanges(serverState: ServerState) {
Expand Down
2 changes: 2 additions & 0 deletions server/src/services/initialization/indexWorkspaceFolders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ async function scanForHardhatProjectsAndAppend(
(hhcf) =>
new HardhatProject(
path.dirname(decodeUriAndRemoveFilePrefix(hhcf)),
hhcf,
workspaceFolder
)
);
Expand Down Expand Up @@ -99,6 +100,7 @@ async function indexWorkspaceFolder(
// documentsUri,
// this.logger
// );

logger.info(`Scan complete, ${documentsUri.length} sol files found`);

// Init all documentAnalyzers
Expand Down
1 change: 1 addition & 0 deletions server/test/helpers/setupMockConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export function setupMockConnection() {
}
),
sendDiagnostics: sinon.spy(),
onRequest: sinon.spy(),
onExit: sinon.spy(),
};
}
10 changes: 9 additions & 1 deletion server/test/helpers/setupMockLanguageServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import {
HoverParams,
Hover,
} from "vscode-languageserver/node";
import setupServer from "../../src/server";
import setupServer, {
GetSolFileDetailsParams,
GetSolFileDetailsResponse,
} from "../../src/server";
import { setupMockCompilerProcessFactory } from "./setupMockCompilerProcessFactory";
import { setupMockConnection } from "./setupMockConnection";
import { waitUntil } from "./waitUntil";
Expand Down Expand Up @@ -53,6 +56,9 @@ export type OnRenameRequest = (
params: RenameParams
) => WorkspaceEdit | undefined | null;
export type OnHover = (params: HoverParams) => Hover | null;
export type OnRequest = (
params: GetSolFileDetailsParams
) => GetSolFileDetailsResponse;

export async function setupMockLanguageServer({
projects,
Expand Down Expand Up @@ -116,6 +122,7 @@ export async function setupMockLanguageServer({
const renameRequest: OnRenameRequest =
mockConnection.onRenameRequest.getCall(0).firstArg;
const hover: OnHover = mockConnection.onHover.getCall(0).firstArg;
const request: OnRequest = mockConnection.onRequest.getCall(0).args[1];

const didOpenTextDocument =
mockConnection.onDidOpenTextDocument.getCall(0).firstArg;
Expand Down Expand Up @@ -173,6 +180,7 @@ export async function setupMockLanguageServer({
implementation,
renameRequest,
hover,
request,
},
};
}
1 change: 1 addition & 0 deletions server/test/parser/analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ async function runIndexing(
const exampleProjects = {
[rootPath]: new HardhatProject(
exampleWorkspaceFolder.uri,
path.join(exampleWorkspaceFolder.uri, "hardhat.config.ts"),
exampleWorkspaceFolder
),
};
Expand Down
Loading

0 comments on commit db8956c

Please sign in to comment.