diff --git a/.idea/.idea.CSharpier/.idea/indexLayout.xml b/.idea/.idea.CSharpier/.idea/indexLayout.xml index 6122498e0..677d79821 100644 --- a/.idea/.idea.CSharpier/.idea/indexLayout.xml +++ b/.idea/.idea.CSharpier/.idea/indexLayout.xml @@ -1,9 +1,7 @@ - - Src/CSharpier.VSCode - + ../../Users/bela/.nuget/packages/scriban/4.0.1/src/Scriban diff --git a/CSharpier.sln.DotSettings b/CSharpier.sln.DotSettings index d69c77e21..708b98810 100644 --- a/CSharpier.sln.DotSettings +++ b/CSharpier.sln.DotSettings @@ -1,5 +1,6 @@  True + True True True True diff --git a/Src/CSharpier.Cli/EditorConfig/EditorConfigParser.cs b/Src/CSharpier.Cli/EditorConfig/EditorConfigParser.cs index 61239710b..bac4df510 100644 --- a/Src/CSharpier.Cli/EditorConfig/EditorConfigParser.cs +++ b/Src/CSharpier.Cli/EditorConfig/EditorConfigParser.cs @@ -2,6 +2,11 @@ namespace CSharpier.Cli.EditorConfig; +// TODO for a given directory find the config in it and going up til root +// keep track of directories + their corresponding configs +// if searching a new directory and we go up to a parent that contains the first config, use that +// how many directories would we run into? enough to matter? +// TODO !!!!!!!!!!!!!!!!!! an easy fix, is to pass a flag to not go deeper when running this via piping files!!! internal static class EditorConfigParser { /// Finds all configs above the given directory as well as within the subtree of this directory @@ -17,6 +22,7 @@ IgnoreFile ignoreFile } var directoryInfo = fileSystem.DirectoryInfo.FromDirectoryName(directoryName); + // TODO this is probably killing performance if nothing else when piping a single file var editorConfigFiles = directoryInfo .EnumerateFiles(".editorconfig", SearchOption.AllDirectories) .Where(x => !ignoreFile.IsIgnored(x.FullName)) diff --git a/Src/CSharpier.Cli/Program.cs b/Src/CSharpier.Cli/Program.cs index 517d7d29a..f4aa95653 100644 --- a/Src/CSharpier.Cli/Program.cs +++ b/Src/CSharpier.Cli/Program.cs @@ -111,6 +111,8 @@ CancellationToken cancellationToken var exitCode = 0; + // TODO warm file somewhere around here + while (true) { while (true) diff --git a/Src/CSharpier.Rider/CONTRIBUTING.md b/Src/CSharpier.Rider/CONTRIBUTING.md index 3012496af..0c47ef60f 100644 --- a/Src/CSharpier.Rider/CONTRIBUTING.md +++ b/Src/CSharpier.Rider/CONTRIBUTING.md @@ -3,6 +3,9 @@ Useful links - https://plugins.jetbrains.com/docs/intellij/welcome.html - https://developerlife.com/2021/03/13/ij-idea-plugin-advanced/ +Initial Setup +- need the java 17 jdk + Local testing - use "Run Plugin" configuration while in intellij to launch the plugin into a dev instance of rider - To see logs diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java index 61789fbdd..243b0041a 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java @@ -34,6 +34,9 @@ public void ensureVersionInstalled(String version) throws Exception { } } catch (Exception ex) { + // TODO somehow I got a bunch of the versions to install that were missing dotnet-csharpier in the root of the custom path + // this needs to do a better job of figuring that out and reporting it. + // I think when this fails to install, then the other stuff gets stuck in an infinite loop logger.warn("Exception while running 'dotnet csharpier --version' in " + pathToDirectoryForVersion, ex); } diff --git a/Src/CSharpier.VSCode/CHANGELOG.md b/Src/CSharpier.VSCode/CHANGELOG.md index 21e1a6f01..0808b9c97 100644 --- a/Src/CSharpier.VSCode/CHANGELOG.md +++ b/Src/CSharpier.VSCode/CHANGELOG.md @@ -1,3 +1,6 @@ +## [1.5.0] +- Improved error handling and reporting around csharpier failing to install or run + ## [1.3.6] - Fix bug where 2nd instance of VSCode was not able to format code diff --git a/Src/CSharpier.VSCode/package.json b/Src/CSharpier.VSCode/package.json index 146436931..f3bd32627 100644 --- a/Src/CSharpier.VSCode/package.json +++ b/Src/CSharpier.VSCode/package.json @@ -2,7 +2,7 @@ "name": "csharpier-vscode", "displayName": "CSharpier - Code formatter", "description": "Code formatter using csharpier", - "version": "1.3.6", + "version": "1.5.0", "publisher": "csharpier", "author": "CSharpier", "homepage": "https://marketplace.visualstudio.com/items?itemName=csharpier.csharpier-vscode", @@ -47,6 +47,11 @@ "type": "boolean", "default": false, "description": "Enable debug logs." + }, + "csharpier.dev.customPath": { + "type": "string", + "default": "", + "description": "Path to directory containing dotnet-csharpier - used for testing the extension with new versions of csharpier." } } } diff --git a/Src/CSharpier.VSCode/src/CSharpierProcessPipeMultipleFiles.ts b/Src/CSharpier.VSCode/src/CSharpierProcessPipeMultipleFiles.ts index cd248d8bc..88bea39d1 100644 --- a/Src/CSharpier.VSCode/src/CSharpierProcessPipeMultipleFiles.ts +++ b/Src/CSharpier.VSCode/src/CSharpierProcessPipeMultipleFiles.ts @@ -7,6 +7,7 @@ export class CSharpierProcessPipeMultipleFiles implements ICSharpierProcess { private callbacks: ((result: string) => void)[] = []; private logger: Logger; private nextFile: string = ""; + private processFailedToStart = false; constructor(logger: Logger, csharpierPath: string, workingDirectory: string) { this.logger = logger; @@ -26,11 +27,29 @@ export class CSharpierProcessPipeMultipleFiles implements ICSharpierProcess { env: { ...process.env, DOTNET_NOLOGO: "1" }, }); + csharpierProcess.on("error", data => { + this.logger.warn( + "Failed to spawn the needed csharpier process. Formatting cannot occur.", + data, + ); + this.processFailedToStart = true; + while (this.callbacks.length > 0) { + const callback = this.callbacks.shift(); + if (callback) { + callback(""); + } + } + }); + + csharpierProcess.stderr.on("data", chunk => { + this.logger.warn("Received data on stderr from the running charpier process", chunk); + }); + csharpierProcess.stdout.on("data", chunk => { this.logger.debug("Got chunk of size " + chunk.length); this.nextFile += chunk; - const number = this.nextFile.indexOf("\u0003"); - if (number >= 0) { + let number = this.nextFile.indexOf("\u0003"); + while (number >= 0) { this.logger.debug("Got last chunk with ETX at " + number); const result = this.nextFile.substring(0, number); this.nextFile = this.nextFile.substring(number + 1); @@ -44,6 +63,8 @@ export class CSharpierProcessPipeMultipleFiles implements ICSharpierProcess { callback(result); } + + number = this.nextFile.indexOf("\u0003"); } }); @@ -51,6 +72,13 @@ export class CSharpierProcessPipeMultipleFiles implements ICSharpierProcess { }; formatFile(content: string, filePath: string): Promise { + if (this.processFailedToStart) { + this.logger.warn("CSharpier proccess failed to start. Formatting cannot occur."); + return new Promise(resolve => { + resolve(""); + }); + } + this.process.stdin.write(filePath); this.process.stdin.write("\u0003"); this.process.stdin.write(content); diff --git a/Src/CSharpier.VSCode/src/CSharpierProcessProvider.ts b/Src/CSharpier.VSCode/src/CSharpierProcessProvider.ts index 62684a856..8312538ac 100644 --- a/Src/CSharpier.VSCode/src/CSharpierProcessProvider.ts +++ b/Src/CSharpier.VSCode/src/CSharpierProcessProvider.ts @@ -209,7 +209,13 @@ export class CSharpierProcessProvider implements Disposable { return NullCSharpierProcess.instance; } - this.customPathInstaller.ensureVersionInstalled(version); + if (!this.customPathInstaller.ensureVersionInstalled(version)) { + window.showErrorMessage( + "CSharpier could not be set up properly so formatting is not currently supported. See Output - CSharpier for details.", + ); + return NullCSharpierProcess.instance; + } + const customPath = this.customPathInstaller.getPathForVersion(version); this.logger.debug(`Adding new version ${version} process for ${directory}`); diff --git a/Src/CSharpier.VSCode/src/CustomPathInstaller.ts b/Src/CSharpier.VSCode/src/CustomPathInstaller.ts index b646f2c8c..422beae8b 100644 --- a/Src/CSharpier.VSCode/src/CustomPathInstaller.ts +++ b/Src/CSharpier.VSCode/src/CustomPathInstaller.ts @@ -2,55 +2,77 @@ import { Logger } from "./Logger"; import * as path from "path"; import * as fs from "fs"; import { execSync } from "child_process"; +import { workspace } from "vscode"; export class CustomPathInstaller { logger: Logger; + customPath: string; constructor(logger: Logger) { this.logger = logger; + this.customPath = + workspace.getConfiguration("csharpier").get("dev.customPath") ?? ""; } - public ensureVersionInstalled(version: string) { + public ensureVersionInstalled(version: string): boolean { if (!version) { - return; + return false; } + if (this.customPath !== "") { + this.logger.debug("Using csharpier at a custom path of " + this.customPath); + return true; + } + const pathToDirectoryForVersion = this.getDirectoryForVersion(version); if (fs.existsSync(pathToDirectoryForVersion)) { - try { - const output = execSync(`${this.getPathForVersion(version)} --version`, { - env: { ...process.env, DOTNET_NOLOGO: "1" }, - }) - .toString() - .trim(); - - this.logger.debug("dotnet csharpier --version output: " + output); - - if (output === version) { - this.logger.debug( - "CSharpier at " + pathToDirectoryForVersion + " already exists", - ); - return; - } - } catch (error: any) { - const message = !error.stderr ? error.toString() : error.stderr.toString(); - this.logger.warn( - "Exception while running 'dotnet csharpier --version' in " + - pathToDirectoryForVersion, - message, - ); + if (this.validateInstall(pathToDirectoryForVersion, version)) { + return true; } this.logger.debug( `Removing directory at ${pathToDirectoryForVersion} because it appears to be corrupted`, ); - fs.rmdirSync(pathToDirectoryForVersion, { recursive: true }); + fs.rmSync(pathToDirectoryForVersion, { recursive: true, force: true }); } const command = `dotnet tool install csharpier --version ${version} --tool-path "${pathToDirectoryForVersion}"`; + this.logger.debug("Running " + command); execSync(command); + + return this.validateInstall(pathToDirectoryForVersion, version); + } + + private validateInstall(pathToDirectoryForVersion: string, version: string): boolean { + try { + const output = execSync(`${this.getPathForVersion(version)} --version`, { + env: { ...process.env, DOTNET_NOLOGO: "1" }, + }) + .toString() + .trim(); + + this.logger.debug("dotnet csharpier --version output: " + output); + + if (output.split("+")[0] === version) { + this.logger.debug("CSharpier at " + pathToDirectoryForVersion + " already exists"); + return true; + } + } catch (error: any) { + const message = !error.stderr ? error.toString() : error.stderr.toString(); + this.logger.warn( + "Exception while running 'dotnet csharpier --version' in " + + pathToDirectoryForVersion, + message, + ); + } + + return false; } private getDirectoryForVersion(version: string) { + if (this.customPath !== "") { + return this.customPath; + } + const result = process.platform !== "win32" ? path.resolve(process.env.HOME!, ".cache/csharpier", version)