Skip to content

Commit

Permalink
Modify VSCode extension to use dotnet tool list + only warn to instal… (
Browse files Browse the repository at this point in the history
#1323)

This modifies the VSCode extension in the following ways
- Instead of looking for dotnet-tools.json files in the current
directory and parent directories the extension runs `dotnet tool list`
and parses the outpud looking for the csharpier version.
- Instead of running `dotnet csharpier --version` to look for the global
version it repeats the above step with `dotnet tool list -g`
- The "You need to install csharpier" window was popping up every time
you opened a file if it couldn't find an install. The other extensions
were limited to showing the warning a single time. VSCode now only shows
it a single time.
- Files under `/DecompilationMetadataAsSourceFileProvider/` will never
have the warning show. This is where the c# dev kit decompiles code.

#1267
  • Loading branch information
belav authored Aug 18, 2024
1 parent 6cb3821 commit 2456512
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 41 deletions.
5 changes: 5 additions & 0 deletions Src/CSharpier.VSCode/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.8.0
- Use `dotnet tool list` to look for both local and global installs of csharpier
- Only show the "you need to install csharpier" notification once per run
- Exclude some directories from the "you need to install csharpier" notification

## [1.7.3]
- Only use CSharpier Server on 0.29.0+
- Add option to bypass csharpier server.
Expand Down
2 changes: 1 addition & 1 deletion Src/CSharpier.VSCode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "csharpier-vscode",
"displayName": "CSharpier - Code formatter",
"description": "Code formatter using csharpier",
"version": "1.7.3",
"version": "1.8.0",
"publisher": "csharpier",
"author": "CSharpier",
"homepage": "https://marketplace.visualstudio.com/items?itemName=csharpier.csharpier-vscode",
Expand Down
90 changes: 50 additions & 40 deletions Src/CSharpier.VSCode/src/CSharpierProcessProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { execDotNet } from "./DotNetProvider";
import { NullCSharpierProcess } from "./NullCSharpierProcess";
import { CSharpierProcessServer } from "./CSharpierProcessServer";
import { ICSharpierProcess2 } from "./ICSharpierProcess";
import { runFunctionsUntilResultFound } from "./RunFunctionsUntilResultFound";

export class CSharpierProcessProvider implements Disposable {
warnedForOldVersion = false;
Expand All @@ -37,7 +38,8 @@ export class CSharpierProcessProvider implements Disposable {
);

this.disableCSharpierServer =
workspace.getConfiguration("csharpier").get<boolean>("dev.disableCSharpierServer") ?? false;
workspace.getConfiguration("csharpier").get<boolean>("dev.disableCSharpierServer") ??
false;

window.onDidChangeActiveTextEditor((event: TextEditor | undefined) => {
if (event?.document?.languageId !== "csharp") {
Expand Down Expand Up @@ -114,6 +116,51 @@ export class CSharpierProcessProvider implements Disposable {
};

private getCSharpierVersion = (directoryThatContainsFile: string): string => {
const csharpierVersion = runFunctionsUntilResultFound(
() => this.findVersionInCsProjOfParentsDirectories(directoryThatContainsFile),
() => this.findCSharpierVersionInToolOutput(directoryThatContainsFile, false),
() => this.findCSharpierVersionInToolOutput(directoryThatContainsFile, true),
);

if (!csharpierVersion) {
return "";
}

const versionWithoutHash = csharpierVersion.split("+")[0];
this.logger.debug(`Using ${versionWithoutHash} as the version number.`);
return versionWithoutHash;
};

private findCSharpierVersionInToolOutput = (
directoryThatContainsFile: string,
isGlobal: boolean,
) => {
const command = `tool list${isGlobal ? " -g" : ""}`;
const output = execDotNet(command, directoryThatContainsFile).toString().trim();

this.logger.debug(`Running 'dotnet ${command}' to look for version`);
this.logger.debug(`Output was: \n${output}`);

const lines = output
.split("\n")
.map(line => line.trim())
.filter(line => line.length > 0);

// The first two lines are headers
for (let i = 2; i < lines.length; i++) {
const columns = lines[i].split(/\s{2,}/);
if (columns.length >= 2) {
if (columns[0].toLowerCase() === "csharpier") {
return columns[1];
}
}
}
};

private findVersionInCsProjOfParentsDirectories = (directoryThatContainsFile: string) => {
this.logger.debug(
`Looking for csproj in or above ${directoryThatContainsFile} that references CSharpier.MsBuild`,
);
let currentDirectory = directoryThatContainsFile;
let parentNumber = 0;
while (parentNumber < 30) {
Expand All @@ -122,46 +169,13 @@ export class CSharpierProcessProvider implements Disposable {
return csProjVersion;
}

const dotnetToolsPath = path.join(currentDirectory, ".config/dotnet-tools.json");
this.logger.debug(`Looking for ${dotnetToolsPath}`);
if (fs.existsSync(dotnetToolsPath)) {
const data = JSON.parse(fs.readFileSync(dotnetToolsPath).toString());
const version = data.tools.csharpier?.version;
if (version) {
this.logger.debug("Found version " + version + " in " + dotnetToolsPath);
return version;
}
}

const nextDirectory = path.join(currentDirectory, "..");
if (nextDirectory === currentDirectory) {
break;
}
currentDirectory = nextDirectory;
parentNumber++;
}

this.logger.debug(
"Unable to find dotnet-tools.json, falling back to running dotnet csharpier --version",
);

let outputFromCsharpier: string;

try {
outputFromCsharpier = execDotNet(`csharpier --version`, directoryThatContainsFile)
.toString()
.trim();

this.logger.debug(`dotnet csharpier --version output: ${outputFromCsharpier}`);
const versionWithoutHash = outputFromCsharpier.split("+")[0];
this.logger.debug(`Using ${versionWithoutHash} as the version number.`);
return versionWithoutHash;
} catch (error: any) {
const message = !error.stderr ? error.toString() : error.stderr.toString();

this.logger.debug("dotnet csharpier --version failed with " + message);
return "";
}
};

private findVersionInCsProj = (currentDirectory: string) => {
Expand Down Expand Up @@ -240,13 +254,9 @@ export class CSharpierProcessProvider implements Disposable {
version,
);
} else if (semver.gte(version, "0.12.0")) {
if (
semver.gte(version, serverVersion)
&& this.disableCSharpierServer
)
{
if (semver.gte(version, serverVersion) && this.disableCSharpierServer) {
this.logger.debug(
"CSharpier server is disabled, falling back to piping via stdin"
"CSharpier server is disabled, falling back to piping via stdin",
);
}

Expand Down
14 changes: 14 additions & 0 deletions Src/CSharpier.VSCode/src/InstallerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class InstallerService {
logger: Logger;
killRunningProcesses: () => void;
extension: Extension<unknown>;
warnedAlready = false;

constructor(logger: Logger, killRunningProcesses: () => void, extension: Extension<unknown>) {
this.logger = logger;
Expand All @@ -21,6 +22,11 @@ export class InstallerService {
}

public displayInstallNeededMessage = (directoryThatContainsFile: string) => {
if (this.warnedAlready || this.ignoreDirectory(directoryThatContainsFile)) {
return;
}

this.warnedAlready = true;
this.logger.error("CSharpier was not found so files may not be formatted.");

this.logger.info(this.extension.extensionKind);
Expand Down Expand Up @@ -119,4 +125,12 @@ export class InstallerService {
},
);
};

private ignoreDirectory(directoryThatContainsFile: string) {
const normalizedPath = directoryThatContainsFile.replace(/\\/g, "/");
return (
normalizedPath.indexOf("/DecompilationMetadataAsSourceFileProvider/") >= 0 ||
normalizedPath === "/"
);
}
}
10 changes: 10 additions & 0 deletions Src/CSharpier.VSCode/src/RunFunctionsUntilResultFound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const runFunctionsUntilResultFound = <T>(...functions: (() => T)[]) => {
for (const possibleFunction of functions) {
const result = possibleFunction();
if (result) {
return result;
}
}

return undefined;
};

0 comments on commit 2456512

Please sign in to comment.