This commit is contained in:
nub31
2025-10-23 18:32:03 +02:00
parent db5d444cf2
commit bfe8b7b18e
4 changed files with 4217 additions and 177 deletions

View File

@@ -1,12 +1,10 @@
using NubLang.Ast;
using NubLang.Generation;
using NubLang.Syntax;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
namespace NubLang.LSP;
public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher, ILanguageServerFacade server)
public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
{
private readonly Dictionary<string, SyntaxTree> _syntaxTrees = new();
private readonly Dictionary<string, CompilationUnit> _compilationUnits = new();
@@ -29,47 +27,37 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher, ILangua
_syntaxTrees[path] = parseResult;
}
Generate();
foreach (var (fsPath, syntaxTree) in _syntaxTrees)
{
var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList());
var typeChecker = new TypeChecker(syntaxTree, modules);
var result = typeChecker.Check();
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
_compilationUnits[fsPath] = result;
}
}
public void UpdateFile(DocumentUri path)
{
var fsPath = path.GetFileSystemPath();
var text = File.ReadAllText(fsPath);
var tokenizer = new Tokenizer(fsPath, text);
tokenizer.Tokenize();
diagnosticsPublisher.Publish(path, tokenizer.Diagnostics);
var parser = new Parser();
var parseResult = parser.Parse(tokenizer.Tokens);
var syntaxTree = parser.Parse(tokenizer.Tokens);
diagnosticsPublisher.Publish(path, parser.Diagnostics);
_syntaxTrees[fsPath] = syntaxTree;
_syntaxTrees[fsPath] = parseResult;
Generate();
}
private void Generate()
{
var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList());
foreach (var (fsPath, syntaxTree) in _syntaxTrees)
{
var typeChecker = new TypeChecker(syntaxTree, modules);
var result = typeChecker.Check();
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
_compilationUnits[fsPath] = result;
var generator = new Generator(result);
var c = generator.Emit();
server.SendNotification("nub/output", new
{
content = c,
path = fsPath
});
}
var typeChecker = new TypeChecker(syntaxTree, modules);
var result = typeChecker.Check();
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
_compilationUnits[fsPath] = result;
}
public void RemoveFile(DocumentUri path)
@@ -79,11 +67,6 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher, ILangua
_compilationUnits.Remove(fsPath);
}
public Dictionary<string, CompilationUnit> GetCompilationUnits()
{
return _compilationUnits;
}
public CompilationUnit? GetCompilationUnit(DocumentUri path)
{
return _compilationUnits.GetValueOrDefault(path.GetFileSystemPath());

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,12 @@
"Programming Languages"
],
"main": "./out/extension.js",
"files": [
"out",
"server",
"syntaxes",
"language-configuration.json"
],
"contributes": {
"languages": [
{
@@ -31,31 +37,17 @@
"scopeName": "source.nub",
"path": "./syntaxes/nub.tmLanguage.json"
}
],
"commands": [
{
"command": "nub.openOutput",
"title": "Nub: Show Output",
"icon": "$(open-preview)"
}
],
"menus": {
"editor/title": [
{
"command": "nub.openOutput",
"when": "editorLangId == nub || resourceExtname == .nub",
"group": "navigation"
}
]
}
]
},
"scripts": {
"build": "tsc -p ./",
"watch": "tsc -watch -p ./"
"watch": "tsc -watch -p ./",
"package": "vsce package"
},
"devDependencies": {
"@types/node": "22.x",
"@types/vscode": "^1.105.0",
"@vscode/vsce": "^3.6.2",
"typescript": "^5.9.3"
},
"dependencies": {

View File

@@ -3,10 +3,8 @@ import vscode from 'vscode';
import { LanguageClient, TransportKind } from 'vscode-languageclient/node';
let client: LanguageClient;
let outputPanel: vscode.WebviewPanel | undefined;
const outputCache = new Map<string, string>();
export function activate(context: vscode.ExtensionContext) {
export async function activate(context: vscode.ExtensionContext) {
const serverExecutable = path.join(context.asAbsolutePath('server'), "nublsp");
client = new LanguageClient(
@@ -34,129 +32,9 @@ export function activate(context: vscode.ExtensionContext) {
}
);
client.onNotification("nub/output", (params: { path: string, content: string }) => {
const normalizedPath = vscode.Uri.file(params.path).fsPath;
outputCache.set(normalizedPath, params.content);
if (outputPanel && vscode.window.activeTextEditor) {
const activePath = vscode.window.activeTextEditor.document.uri.fsPath;
if (activePath === normalizedPath) {
updateOutputPanel(params.content);
}
}
});
const openOutputCommand = vscode.commands.registerCommand('nub.openOutput', async () => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showWarningMessage('No active editor found');
return;
}
const filePath = editor.document.uri.fsPath;
const cachedOutput = outputCache.get(filePath);
if (outputPanel) {
outputPanel.reveal(vscode.ViewColumn.Beside);
} else {
outputPanel = vscode.window.createWebviewPanel(
'nubOutput',
'C Output',
vscode.ViewColumn.Beside,
{
enableScripts: true,
retainContextWhenHidden: true
}
);
outputPanel.onDidDispose(() => {
outputPanel = undefined;
});
}
if (cachedOutput) {
updateOutputPanel(cachedOutput);
} else {
updateOutputPanel('// Waiting for C output...');
}
});
const changeEditorSubscription = vscode.window.onDidChangeActiveTextEditor(editor => {
if (outputPanel && editor) {
const filePath = editor.document.uri.fsPath;
const cachedOutput = outputCache.get(filePath);
if (cachedOutput) {
updateOutputPanel(cachedOutput);
} else {
updateOutputPanel('// No C output available for this file');
}
}
});
context.subscriptions.push(openOutputCommand, changeEditorSubscription);
client.start();
}
function updateOutputPanel(content: string) {
if (!outputPanel) return;
outputPanel.webview.html = getWebviewContent(content);
}
function getWebviewContent(content: string): string {
const escapedContent = content
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nub C Output</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs2015.min.css">
<style>
body {
margin: 0;
padding: 16px;
font-family: 'Consolas', 'Courier New', monospace;
font-size: 14px;
line-height: 1.5;
background-color: var(--vscode-editor-background);
color: var(--vscode-editor-foreground);
}
pre {
margin: 0;
background-color: transparent !important;
padding: 0;
}
code {
font-family: 'Consolas', 'Courier New', monospace;
background-color: transparent !important;
}
.hljs {
background-color: transparent;
color: var(--vscode-editor-foreground);
}
</style>
</head>
<body>
<pre><code class="language-c" id="code-content">${escapedContent}</code></pre>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/c.min.js"></script>
<script>
hljs.highlightAll();
</script>
</body>
</html>`;
}
export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;