Skip to content

Commit

Permalink
Rider - Adding support for csharpier server, release 1.5.3 (#1157)
Browse files Browse the repository at this point in the history
* Adding support for csharpier server, release 1.5.3

* self code review

* Get to build with latest
  • Loading branch information
belav authored Jan 28, 2024
1 parent d3dddf7 commit a8d07b2
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 40 deletions.
3 changes: 3 additions & 0 deletions Src/CSharpier.Rider/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

# csharpier-rider Changelog

## [1.5.3]
- Add experimental support for CSharpier server

## [1.5.2]
- Support for a CSharpier version format of 0.X.Y+HASH in dotnet-tools.json

Expand Down
19 changes: 4 additions & 15 deletions Src/CSharpier.Rider/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ fun properties(key: String) = project.findProperty(key).toString()

plugins {
id("java")
id("org.jetbrains.kotlin.jvm") version "1.6.0"
id("org.jetbrains.intellij") version "1.3.0"
id("org.jetbrains.changelog") version "1.3.1"
id("org.jetbrains.kotlin.jvm") version "1.9.21"
id("org.jetbrains.intellij") version "1.17.0"
id("org.jetbrains.changelog") version "2.2.0"
id("org.jetbrains.qodana") version "0.1.13"
id("com.jetbrains.rdgen") version "2021.3.4"
id("com.jetbrains.rdgen") version "2023.3.2"
}

group = properties("pluginGroup")
Expand Down Expand Up @@ -45,17 +45,6 @@ qodana {
}

tasks {
// Set the JVM compatibility versions
properties("javaVersion").let {
withType<JavaCompile> {
sourceCompatibility = it
targetCompatibility = it
}
withType<KotlinCompile> {
kotlinOptions.jvmTarget = it
}
}

runIde {
maxHeapSize = "1500m"
// maybe autoReloadPlugins = false
Expand Down
18 changes: 5 additions & 13 deletions Src/CSharpier.Rider/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,21 @@

pluginGroup = com.intellij.csharpier
pluginName = csharpier
pluginVersion = 1.5.2
pluginVersion = 1.5.3

# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
# for insight into build numbers and IntelliJ Platform versions.
pluginSinceBuild = 212
pluginSinceBuild = 222

# IntelliJ Platform Properties -> https://github.com/JetBrains/gradle-intellij-plugin#intellij-platform-properties
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType = RD
# trying to change this to a higher version results in builds that don't work, but it isn't clear why. The only reason to go
# to higher versions seems to be to get deprecated notices, so things are probably fine as is for now.
platformVersion = 2021.2.1
platformVersion = 2022.2.1

# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
platformPlugins =

# Java language level used to compile sources and to generate the files for - Java 11 is required since 2020.3
javaVersion = 11

# Gradle Releases -> https://github.com/gradle/gradle/releases
gradleVersion = 7.3
gradleVersion = 8.5

# Opt-out flag for bundling Kotlin standard library.
# See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details.
# suppress inspection "UnusedProperty"
kotlin.stdlib.default.dependency = false
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.jetbrains.annotations.NotNull;
import org.w3c.dom.Node;

Expand Down Expand Up @@ -119,8 +118,7 @@ private String getCSharpierVersion(String directoryThatContainsFile) {
try {
while (true) {
var csProjVersion = this.FindVersionInCsProj(currentDirectory);
if (csProjVersion != null)
{
if (csProjVersion != null) {
return csProjVersion;
}

Expand Down Expand Up @@ -180,9 +178,9 @@ private String FindVersionInCsProj(Path currentDirectory) {

try {
var xmlDocument = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(pathToCsProj);
.newInstance()
.newDocumentBuilder()
.parse(pathToCsProj);

var selector = XPathFactory.newInstance().newXPath();
var node = (Node) selector.compile("//PackageReference[@Include='CSharpier.MsBuild']").evaluate(xmlDocument, XPathConstants.NODE);
Expand Down Expand Up @@ -223,6 +221,10 @@ private ICSharpierProcess setupCSharpierProcess(String directory, String version
var installedVersion = version.split("\\.");
var versionWeCareAbout = Integer.parseInt(installedVersion[1]);

if (CSharpierSettings.getInstance(this.project).getUseServer()) {
return new CSharpierProcessServer(customPath);
}

if (versionWeCareAbout < 12) {
if (!this.warnedForOldVersion) {
var content = "Please upgrade to CSharpier >= 0.12.0 for bug fixes and improved formatting speed.";
Expand Down Expand Up @@ -258,7 +260,7 @@ private void displayFailureMessage() {
var message = "CSharpier could not be set up properly so formatting is not currently supported. See log file for more details.";
var notification = NotificationGroupManager.getInstance().getNotificationGroup("CSharpier")
.createNotification(title, message, NotificationType.WARNING);
notification.addAction(new OpenUrlAction("Read More","https://csharpier.com/docs/EditorsTroubleshooting"));
notification.addAction(new OpenUrlAction("Read More", "https://csharpier.com/docs/EditorsTroubleshooting"));
notification.notify(this.project);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package com.intellij.csharpier;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import com.google.gson.Gson;

public class CSharpierProcessServer implements ICSharpierProcess, Disposable {
private final Gson gson = new Gson();
private final String csharpierPath;
private Logger logger = CSharpierLogger.getInstance();
private int port;
private Process process = null;
public boolean processFailedToStart;

public CSharpierProcessServer(String csharpierPath) {
this.csharpierPath = csharpierPath;
this.startProcess();

this.logger.debug("Warm CSharpier with initial format");
// warm by formatting a file twice, the 3rd time is when it gets really fast
this.formatFile("public class ClassName { }", "/Temp/Test.cs");
this.formatFile("public class ClassName { }", "/Temp/Test.cs");
}

private void startProcess() {
try {
var processBuilder = new ProcessBuilder(this.csharpierPath, "--server");
processBuilder.redirectErrorStream(true);
processBuilder.environment().put("DOTNET_NOLOGO", "1");
this.process = processBuilder.start();

var reader = new BufferedReader(new InputStreamReader(this.process.getInputStream()));

var executor = Executors.newSingleThreadExecutor();
var future = executor.submit(() -> reader.readLine());

String output = null;
try {
output = future.get(2, TimeUnit.SECONDS);
} catch (TimeoutException e) {
this.logger.warn("Spawning the csharpier server timed out. Formatting cannot occur.");
this.process.destroy();
return;
}

if (!this.process.isAlive()) {
this.logger.warn("Spawning the csharpier server failed because it exited. " + output);
this.processFailedToStart = true;
return;
}

var portString = output.replace("Started on ", "");
this.port = Integer.parseInt(portString);

this.logger.debug("Connecting via port " + portString);

} catch (Exception e) {
this.logger.warn("Failed to spawn the needed csharpier server.", e);
this.processFailedToStart = true;
}
}

@Override
public String formatFile(String content, String filePath) {
if (this.processFailedToStart) {
this.logger.warn("CSharpier process failed to start. Formatting cannot occur.");
return "";
}

var data = new FormatFileDto();
data.fileContents = content;
data.fileName = filePath;

var url = "http://localhost:" + this.port + "/format";


try {
var url1 = new URL(url);

var connection = (HttpURLConnection) url1.openConnection();

connection.setRequestMethod("POST");

connection.setRequestProperty("Content-Type", "application/json; utf-8");

connection.setDoOutput(true);
connection.setDoInput(true);

var outputStream = connection.getOutputStream();
var writer = new OutputStreamWriter(outputStream, "UTF-8");
writer.write(this.gson.toJson(data));
writer.flush();
writer.close();
outputStream.close();

var responseCode = connection.getResponseCode();
if (responseCode != 200) {
connection.disconnect();
return "";
}

InputStreamReader reader = new InputStreamReader(connection.getInputStream());
var result = gson.fromJson(reader, FormatFileResult.class);
reader.close();

connection.disconnect();

return result.formattedFile != null ? result.formattedFile : "";

} catch (Exception e) {
this.logger.warn("Failed posting to the csharpier server.", e);
}

return "";
}

@Override
public void dispose() {
if (this.process != null) {
this.process.destroy();
}
}

private class FormatFileDto {
public String fileContents;
public String fileName;
}

private class FormatFileResult {
public String formattedFile;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ public void setCustomPath(String customPath) {
this.customPath = customPath;
}

private boolean useServer;

public boolean getUseServer() {
return this.useServer;
}

public void setUseServer(boolean useServer) {
this.useServer = useServer;
}

@Override
public CSharpierSettings getState() {
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;


public class CSharpierSettingsComponent implements SearchableConfigurable {
private final Project project;
private JCheckBox runOnSaveCheckBox = new JCheckBox("Run on Save");
private JTextField customPathTextField = new JTextField("Path to directory containing dotnet-csharpier - used for testing the extension with new versions of csharpier.");
private JBCheckBox runOnSaveCheckBox = new JBCheckBox("Run on Save");
private JBCheckBox useServerCheckBox = new JBCheckBox("Use CSharpier Server - experimental support as of 0.27.2");
private JBTextField customPathTextField = new JBTextField();

public CSharpierSettingsComponent(@NotNull Project project) {
this.project = project;
Expand All @@ -33,16 +38,26 @@ public String getDisplayName() {

@Override
public @Nullable JComponent createComponent() {
var leftIndent = 20;
var topInset = 10;

return FormBuilder.createFormBuilder()
.addComponent(this.runOnSaveCheckBox)
.addComponent(this.customPathTextField)
.addLabeledComponent(new JBLabel("General Settings"), new JSeparator())
.setFormLeftIndent(leftIndent)
.addComponent(this.runOnSaveCheckBox, topInset)
.setFormLeftIndent(0)
.addLabeledComponent(new JBLabel("Developer Settings"), new JSeparator(), 20)
.setFormLeftIndent(leftIndent)
.addLabeledComponent(new JBLabel("Directory of custom dotnet-csharpier:"), this.customPathTextField, topInset, false)
.addComponent(this.useServerCheckBox, topInset)
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}

@Override
public boolean isModified() {
return CSharpierSettings.getInstance(this.project).getRunOnSave() != this.runOnSaveCheckBox.isSelected()
|| CSharpierSettings.getInstance(this.project).getUseServer() != this.useServerCheckBox.isSelected()
|| CSharpierSettings.getInstance(this.project).getCustomPath() != this.customPathTextField.getText();
}

Expand All @@ -52,12 +67,14 @@ public void apply() throws ConfigurationException {

settings.setRunOnSave(this.runOnSaveCheckBox.isSelected());
settings.setCustomPath(this.customPathTextField.getText());
settings.setUseServer(this.useServerCheckBox.isSelected());
}

@Override
public void reset() {
var settings = CSharpierSettings.getInstance(this.project);
this.runOnSaveCheckBox.setSelected(settings.getRunOnSave());
this.useServerCheckBox.setSelected(settings.getUseServer());
this.customPathTextField.setText(settings.getCustomPath());
}
}

0 comments on commit a8d07b2

Please sign in to comment.