Skip to content

feat: add csharp support via csc direct compilation - #12

Open
Aryan-Raj-7167 wants to merge 2 commits into
Acode-Foundation:mainfrom
Aryan-Raj-7167:add-csharp-support
Open

Aryan-Raj-7167 wants to merge 2 commits into
Acode-Foundation:mainfrom
Aryan-Raj-7167:add-csharp-support

Conversation

@Aryan-Raj-7167

Copy link
Copy Markdown
  • Uses csc (Roslyn compiler) instead of dotnet run for faster execution
  • Includes DOTNET_GCHeapHardLimit workaround for Android memory constraints
  • Generates GlobalUsings.cs to match dotnet new console's implicit usings
  • Caches Program.runtimeconfig.json per project to avoid regeneration

- Uses csc (Roslyn compiler) instead of dotnet run for faster execution
- Includes DOTNET_GCHeapHardLimit workaround for Android memory constraints
- Generates GlobalUsings.cs to match dotnet new console's implicit usings
- Caches Program.runtimeconfig.json per project to avoid regeneration
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds C# support to the Acode runner plugin using csc (Roslyn compiler) invoked via dotnet exec rather than dotnet run, along with Android-specific GC heap environment variables and auto-generated GlobalUsings.cs to match implicit usings from dotnet new console.

  • C# runner command (src/languageRunners.js): Creates a per-filename temp directory in /tmp/csrun_{name}, copies the source to Program.cs, generates GlobalUsings.cs and Program.runtimeconfig.json when missing, compiles with csc.dll, and runs the output Program.dll — all in a single chained shell command.
  • Version bump & docs: plugin.json advances to 1.0.6, changelog.md is updated, and the supported-languages table in readme.md gains a C# row.

Confidence Score: 3/5

The C# runner works for unsaved/content:// files but breaks for .cs files saved to the Alpine filesystem, which is the primary interactive editing location for many users.

The copy step runs after a directory change, using a basename-only path that does not exist in the temp directory. Any user who saves a .cs file in the Alpine home directory and presses Run will hit a cp failure before compilation starts.

src/languageRunners.js — specifically the single-line cmd string for the C# runner

Important Files Changed

Filename Overview
src/languageRunners.js Adds C# runner via csc direct compilation; contains a bug where cp "{file}" fails for saved (file://) files because {file} is a basename but is executed after cd /tmp/csrun_{name}. Also uses 4-space indentation inconsistent with the rest of the file.
changelog.md Adds v1.0.6 changelog entry for C# support — no issues.
plugin.json Bumps version from 1.0.5 to 1.0.6 — no issues.
readme.md Adds C# (.cs) to the supported languages table — no issues.

Reviews (1): Last reviewed commit: "feat: add csharp support via csc direct ..." | Re-trigger Greptile

Comment thread src/languageRunners.js Outdated
extensions: ['cs'],
commands: [
{
cmd: `mkdir -p /tmp/csrun_{name} && cd /tmp/csrun_{name} && cp "{file}" ./Program.cs && export DOTNET_gcServer=0 DOTNET_GCHeapHardLimit=0x10000000 DOTNET_GCgen0size=0x2000000 && CSC=$(find /usr/lib/dotnet/sdk -name "csc.dll" 2>/dev/null | head -1) && REFDIR=$(find /usr/lib/dotnet/packs/Microsoft.NETCore.App.Ref -type d -name "net8.0" 2>/dev/null | head -1) && REFS=$(find "$REFDIR" -name "*.dll" 2>/dev/null | sed 's/^/-r:/' | tr '\n' ' ') && ([ -f Program.runtimeconfig.json ] || printf '{"runtimeOptions":{"tfm":"net8.0","framework":{"name":"Microsoft.NETCore.App","version":"8.0.0"}}}' > Program.runtimeconfig.json) && ([ -f GlobalUsings.cs ] || printf 'global using System;\\nglobal using System.Collections.Generic;\\nglobal using System.Linq;\\nglobal using System.IO;\\nglobal using System.Threading.Tasks;\\n' > GlobalUsings.cs) && dotnet exec "$CSC" -nologo -optimize -langversion:latest $REFS -out:Program.dll Program.cs GlobalUsings.cs && dotnet Program.dll`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 cp "{file}" fails for saved files after cd /tmp/csrun_{name}

The command issues cd /tmp/csrun_{name} first, then cp "{file}" ./Program.cs. In the needsTempFile=false path (files accessed via a file:// URI — i.e., files saved in the Alpine filesystem), {file} is substituted with just the basename of the file (e.g., MyProgram.cs), not an absolute path. Once the shell has changed into /tmp/csrun_{name}, that basename does not exist there, so cp fails with "No such file or directory" and the whole && chain aborts before compilation. The needsTempFile=true path (unsaved/content:// files) is safe because {file} resolves to the absolute /tmp/<filename> in that branch.

The fix is to use {path} instead of {file} in the cp sub-command, or to copy the file before the cd. {path} resolves to the absolute filesystem path in both the saved-file branch (actualPath) and the temp-file branch (tempFile), so it is safe to use unconditionally here.

Comment thread src/languageRunners.js Outdated
Comment on lines +53 to +64
// C#
this.#runners.set('csharp', {
extensions: ['cs'],
commands: [
{
cmd: `mkdir -p /tmp/csrun_{name} && cd /tmp/csrun_{name} && cp "{file}" ./Program.cs && export DOTNET_gcServer=0 DOTNET_GCHeapHardLimit=0x10000000 DOTNET_GCgen0size=0x2000000 && CSC=$(find /usr/lib/dotnet/sdk -name "csc.dll" 2>/dev/null | head -1) && REFDIR=$(find /usr/lib/dotnet/packs/Microsoft.NETCore.App.Ref -type d -name "net8.0" 2>/dev/null | head -1) && REFS=$(find "$REFDIR" -name "*.dll" 2>/dev/null | sed 's/^/-r:/' | tr '\n' ' ') && ([ -f Program.runtimeconfig.json ] || printf '{"runtimeOptions":{"tfm":"net8.0","framework":{"name":"Microsoft.NETCore.App","version":"8.0.0"}}}' > Program.runtimeconfig.json) && ([ -f GlobalUsings.cs ] || printf 'global using System;\\nglobal using System.Collections.Generic;\\nglobal using System.Linq;\\nglobal using System.IO;\\nglobal using System.Threading.Tasks;\\n' > GlobalUsings.cs) && dotnet exec "$CSC" -nologo -optimize -langversion:latest $REFS -out:Program.dll Program.cs GlobalUsings.cs && dotnet Program.dll`,
packages: ['dotnet8-sdk'],
checkCommand: 'dotnet'
}
],
description: 'C# compiler'
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The C# block uses 4-space indentation while every other runner in the file uses tabs. This creates a visible inconsistency in editors and in git diff output.

Suggested change
// C#
this.#runners.set('csharp', {
extensions: ['cs'],
commands: [
{
cmd: `mkdir -p /tmp/csrun_{name} && cd /tmp/csrun_{name} && cp "{file}" ./Program.cs && export DOTNET_gcServer=0 DOTNET_GCHeapHardLimit=0x10000000 DOTNET_GCgen0size=0x2000000 && CSC=$(find /usr/lib/dotnet/sdk -name "csc.dll" 2>/dev/null | head -1) && REFDIR=$(find /usr/lib/dotnet/packs/Microsoft.NETCore.App.Ref -type d -name "net8.0" 2>/dev/null | head -1) && REFS=$(find "$REFDIR" -name "*.dll" 2>/dev/null | sed 's/^/-r:/' | tr '\n' ' ') && ([ -f Program.runtimeconfig.json ] || printf '{"runtimeOptions":{"tfm":"net8.0","framework":{"name":"Microsoft.NETCore.App","version":"8.0.0"}}}' > Program.runtimeconfig.json) && ([ -f GlobalUsings.cs ] || printf 'global using System;\\nglobal using System.Collections.Generic;\\nglobal using System.Linq;\\nglobal using System.IO;\\nglobal using System.Threading.Tasks;\\n' > GlobalUsings.cs) && dotnet exec "$CSC" -nologo -optimize -langversion:latest $REFS -out:Program.dll Program.cs GlobalUsings.cs && dotnet Program.dll`,
packages: ['dotnet8-sdk'],
checkCommand: 'dotnet'
}
],
description: 'C# compiler'
});
// C#
this.#runners.set('csharp', {
extensions: ['cs'],
commands: [
{
cmd: `mkdir -p /tmp/csrun_{name} && cd /tmp/csrun_{name} && cp "{file}" ./Program.cs && export DOTNET_gcServer=0 DOTNET_GCHeapHardLimit=0x10000000 DOTNET_GCgen0size=0x2000000 && CSC=$(find /usr/lib/dotnet/sdk -name "csc.dll" 2>/dev/null | head -1) && REFDIR=$(find /usr/lib/dotnet/packs/Microsoft.NETCore.App.Ref -type d -name "net8.0" 2>/dev/null | head -1) && REFS=$(find "$REFDIR" -name "*.dll" 2>/dev/null | sed 's/^/-r:/' | tr '\n' ' ') && ([ -f Program.runtimeconfig.json ] || printf '{"runtimeOptions":{"tfm":"net8.0","framework":{"name":"Microsoft.NETCore.App","version":"8.0.0"}}}' > Program.runtimeconfig.json) && ([ -f GlobalUsings.cs ] || printf 'global using System;\\nglobal using System.Collections.Generic;\\nglobal using System.Linq;\\nglobal using System.IO;\\nglobal using System.Threading.Tasks;\\n' > GlobalUsings.cs) && dotnet exec "$CSC" -nologo -optimize -langversion:latest $REFS -out:Program.dll Program.cs GlobalUsings.cs && dotnet Program.dll`,
packages: ['dotnet8-sdk'],
checkCommand: 'dotnet'
}
],
description: 'C# compiler'
});

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant