Release-Candidate / vscode-scheme-repl

A Visual Studio Code extension for Chez Scheme, it uses the REPL for autocompletions and to evaluate expressions.
MIT License
14 stars 0 forks source link

Inline evaluation doesn't work and hangs. #20

Closed migraine-user closed 2 months ago

migraine-user commented 3 months ago

On Linux, inline evaluation hangs like the following: image This never evaluates. However, the non-inline functions of the extension work: there are no other issues. I am using the most recent version of the official VS Code with chez scheme 10.0

migraine-user commented 3 months ago

I've attempted to debug the issue on my end, but I was unable to start the debugger on the extension because I was missing the following:

I've never had this issue before, and I'm not sure if it's unique to this extension.

Release-Candidate commented 3 months ago

Thanks for your bug report. I'll try to reproduce it.

The bootstrap*.js files are something VS Code specific, but without them Code doesn't work at all?

Release-Candidate commented 3 months ago

I can't reproduce that on MacOS.

Could you please post the output of the OUTPUT tab, when switched to Chez Scheme REPL? It should say something like "Sent (+ 1 1) to REPL using command chezScheme.evalLastSexp"

Bildschirmfoto 2024-07-02 um 13 41 39

migraine-user commented 3 months ago

Thanks for your bug report. I'll try to reproduce it.

The bootstrap*.js files are something VS Code specific, but without them Code doesn't work at all?

The plugin works when installed normally, but when I git clone and npm install then try the extension debugger on VS Code, it doesn't work. It does not start at all, and I get the dialog message box saying that I am possibly missing the two files I mentioned above and loader.js in that same directory (I do have this file).

I can't reproduce that on MacOS.

Could you please post the output of the OUTPUT tab, when switched to Chez Scheme REPL? It should say something like "Sent (+ 1 1) to REPL using command chezScheme.evalLastSexp"

Bildschirmfoto 2024-07-02 um 13 41 39

There is no output, nor does it try to spawn a repl if it doesn't exist, when I try to do any inline evaluation. I'm not sure if it is sending anything anywhere at all. Other commands like macro expansion with Alt+Enter works just fine. I think it is just the inline evaluation that hangs.

Release-Candidate commented 3 months ago

There is no output, nor does it try to spawn a repl if it doesn't exist, when I try to do any inline evaluation. I'm not sure if it is sending anything anywhere at all. Other commands like macro expansion with Alt+Enter works just fine. I think it is just the inline evaluation that hangs.

I can reproduce the error in a Linux VM. Just to be sure: autocompletion and documentation on hover works for you, right? Because these use the same "internal" REPL as the inline evaluation.

The plugin works when installed normally, but when I git clone and npm install then try the extension debugger on VS Code, it doesn't work. It does not start at all, and I get the dialog message box saying that I am possibly missing the two files I mentioned above and loader.js in that same directory (I do have this file).

Hmm, this sounds strange, I'll try to reproduce that in the Linux VM too. [Edit] Yes, this happens for me too in the Linux VM, but works on MacOS.

You need to run

npm run bundle

to generate the extension in out/extension.js, after that, debugging works.

Release-Candidate commented 3 months ago

You won't believe me! Could it be that you are using the extension "TodoTree" from "Gruntfuggly"? After disabling this extension, everything works in my extension! By chance I use the "TodoTree" extension in this Linux VM but not on MacOS.

This is the stack-trace I got in the "OUTPUT" Tab of "Extension Host", which showed me the culprit:

[error] SyntaxError: Invalid flags: dsu
    at k (/home/roland/.vscode/extensions/gruntfuggly.todo-tree-0.0.226/dist/extension.js:114:74341)
    at Array.d (/home/roland/.vscode/extensions/gruntfuggly.todo-tree-0.0.226/dist/extension.js:114:3580)
    at Object.parse (/home/roland/.vscode/extensions/gruntfuggly.todo-tree-0.0.226/dist/extension.js:114:71938)
    at r.parse (/home/roland/.vscode/extensions/gruntfuggly.todo-tree-0.0.226/dist/extension.js:1:12692)
    at Object.parse (/home/roland/.vscode/extensions/gruntfuggly.todo-tree-0.0.226/dist/extension.js:114:415)
    at l (/home/roland/.vscode/extensions/gruntfuggly.todo-tree-0.0.226/dist/extension.js:52:165)
    at Array.get [as indices] (/home/roland/.vscode/extensions/gruntfuggly.todo-tree-0.0.226/dist/extension.js:52:2895)
    at Re (/home/roland/tmp/vscode-scheme-repl/out/extension.js:16:2643)
    at zr (/home/roland/tmp/vscode-scheme-repl/out/extension.js:16:210)
    at g (/home/roland/tmp/vscode-scheme-repl/out/extension.js:12:1237)
    at Y (/home/roland/tmp/vscode-scheme-repl/out/extension.js:16:2259)
    at vr (/home/roland/tmp/vscode-scheme-repl/out/extension.js:12:1338)
    at g (/home/roland/tmp/vscode-scheme-repl/out/extension.js:12:1070)
    at U (/home/roland/tmp/vscode-scheme-repl/out/extension.js:12:956)
    at Ne (/home/roland/tmp/vscode-scheme-repl/out/extension.js:25:918)
    at /home/roland/tmp/vscode-scheme-repl/out/extension.js:830:29871
migraine-user commented 3 months ago

Nope, it seems like a different error on my end image It seems similar to this issue Maybe this can get fixed if I keep on disabling other extensions. I'll dig around.

migraine-user commented 3 months ago

There is no output, nor does it try to spawn a repl if it doesn't exist, when I try to do any inline evaluation. I'm not sure if it is sending anything anywhere at all. Other commands like macro expansion with Alt+Enter works just fine. I think it is just the inline evaluation that hangs.

I can reproduce the error in a Linux VM. Just to be sure: autocompletion and documentation on hover works for you, right? Because these use the same "internal" REPL as the inline evaluation.

The plugin works when installed normally, but when I git clone and npm install then try the extension debugger on VS Code, it doesn't work. It does not start at all, and I get the dialog message box saying that I am possibly missing the two files I mentioned above and loader.js in that same directory (I do have this file).

Hmm, this sounds strange, I'll try to reproduce that in the Linux VM too. [Edit] Yes, this happens for me too in the Linux VM, but works on MacOS.

You need to run

npm run bundle

to generate the extension in out/extension.js, after that, debugging works.

Yep, the hover and documentation are working fine. It's just the inline evaluation I think.

Release-Candidate commented 3 months ago

Ah, I see. A SIGPIPE means that the connection to the (internal) Scheme REPL has been closed. The question of course is why? And why only when sending something to evaluate and not when asking for completions or documentation?

As I can't do that myself, please add the following additional logging to the file src/evalREPL.ts, at line 322 https://github.com/Release-Candidate/vscode-scheme-repl/blob/main/src/evalREPL.ts#L322

      } else if (out.error) {
            const errMsg = out.error.trim();
            env.outChannel.appendLine(
                `Error sending ${c.cfgSection}.${data.vscodeCommand}: ${errMsg}`
            );
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalErrorDecoration,
                evalDecorations: env.evalErrorDecorations,
                range: data.range,
                text: errMsg,
            });
            decor.removeRange({
                decorations: env.evalDecorations,
                decoration: env.evalDecoration,
                editor: data.editor,
                range: data.range,
            });

and wrap the whole function in a try ... catch.

The whole function should be changed to:

async function evalSexp(
    env: h.Env,
    data: {
        editor: vscode.TextEditor;
        exp: {
            sexp: string;
            startLine: number;
            startCol: number;
        };
        range: vscode.Range;
        vscodeCommand: string;
    }
): Promise<void> {
    try {
        const out = await runREPLCommand(
            env.config,
            data.editor.document,
            data.exp.sexp
        );
        env.outChannel.appendLine(
            `Sent ${data.exp.sexp} to REPL using command ${c.cfgSection}.${data.vscodeCommand}`
        );
        if (out.stderr) {
            const errMsg = out.stderr.trim();
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalErrorDecoration,
                evalDecorations: env.evalErrorDecorations,
                range: data.range,
                text: errMsg,
            });
            decor.removeRange({
                decorations: env.evalDecorations,
                decoration: env.evalDecoration,
                editor: data.editor,
                range: data.range,
            });
        } else if (out.error) {
            const errMsg = out.error.trim();
            env.outChannel.appendLine(
                `Error sending ${c.cfgSection}.${data.vscodeCommand}: ${errMsg}`
            );
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalErrorDecoration,
                evalDecorations: env.evalErrorDecorations,
                range: data.range,
                text: errMsg,
            });
            decor.removeRange({
                decorations: env.evalDecorations,
                decoration: env.evalDecoration,
                editor: data.editor,
                range: data.range,
            });
        } else {
            const match = out.stdout
                ? out.stdout.match(matchREPLResponse("(.+?)"))
                : "";
            const response = match ? match[1].trim() : "";
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalDecoration,
                evalDecorations: env.evalDecorations,
                range: data.range,
                text: response,
            });
            decor.removeRange({
                decorations: env.evalErrorDecorations,
                decoration: env.evalErrorDecoration,
                editor: data.editor,
                range: data.range,
            });
        }
    } catch (err) {
        env.outChannel.appendLine(
            `Error sending ${c.cfgSection}.${data.vscodeCommand}: ${
                (err as Error).message
            }`
        );
    }
}

Then you should see an error message in the "OUTPUT" tab of "Chez Scheme REPL".

Of course, chances are we'll just see ""Unexpected SIGPIPE".

migraine-user commented 3 months ago

I've copied the function definition over, and the error is very weird. That did not append anything to the out channel for both VS Code windows (the one running the debugger and the one being debugged). image However, now there is a new error popping up on the editor for ENOENT. It could be missing some intermediate file needed for the operation. Could you tell me how I could find where this is happening?

migraine-user commented 3 months ago

Sorry, I was looking at the wrong place.

Chez Scheme REPL starting.
Registered all commands
Extension startup finished.
Searching for completions of +
Completion error: spawn scheme ENOENT 
using (filter
      (lambda (x)
        (cond
          [(symbol? x) (equal? "+" (substring (symbol->string x) 0 1))]
          [else #f]))
      (apropos-list "+" (interaction-environment)))
Got completions: 
Sent (expand '(+ 1 1)) to REPL using command chezScheme.expandLastSexp
Sent (expand '(+ 1 1)) to REPL using command chezScheme.expandLastSexp
Sent (+ 1 1) to REPL using command chezScheme.evalLastSexp
Error sending chezScheme.evalLastSexp: spawn scheme ENOENT
Release-Candidate commented 3 months ago

This is the error that I added in the addErrorDecoration part. This means that for example the command/executable scheme has not been found in the PATH when trying to start the REPL.

Release-Candidate commented 3 months ago

Completion error: spawn scheme ENOENT

says that completions don't work either.

Is scheme the correct name of your Chez executable? But on the other hand, it works as interactive REPL. Is the scheme command in a special directory, which isn't part of the "normal" Linux PATH?

Can you please post the output of printenv PATH in the Console of VS Code? And add the output of the PATH to the program, by adding

env.outChannel.appendLine(`PATH: ${process.env.PATH}`);

To the beginning of evalSexp, so that it now is

async function evalSexp(
    env: h.Env,
    data: {
        editor: vscode.TextEditor;
        exp: {
            sexp: string;
            startLine: number;
            startCol: number;
        };
        range: vscode.Range;
        vscodeCommand: string;
    }
): Promise<void> {
    env.outChannel.appendLine(`PATH: ${process.env.PATH}`);
    try {
        const out = await runREPLCommand(
            env.config,
            data.editor.document,
            data.exp.sexp
        );
        env.outChannel.appendLine(
            `Sent ${data.exp.sexp} to REPL using command ${c.cfgSection}.${data.vscodeCommand}`
        );
        if (out.stderr) {
            const errMsg = out.stderr.trim();
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalErrorDecoration,
                evalDecorations: env.evalErrorDecorations,
                range: data.range,
                text: errMsg,
            });
            decor.removeRange({
                decorations: env.evalDecorations,
                decoration: env.evalDecoration,
                editor: data.editor,
                range: data.range,
            });
        } else if (out.error) {
            const errMsg = out.error.trim();
            env.outChannel.appendLine(
                `Error sending ${c.cfgSection}.${data.vscodeCommand}: ${errMsg}`
            );
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalErrorDecoration,
                evalDecorations: env.evalErrorDecorations,
                range: data.range,
                text: errMsg,
            });
            decor.removeRange({
                decorations: env.evalDecorations,
                decoration: env.evalDecoration,
                editor: data.editor,
                range: data.range,
            });
        } else {
            const match = out.stdout
                ? out.stdout.match(matchREPLResponse("(.+?)"))
                : "";
            const response = match ? match[1].trim() : "";
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalDecoration,
                evalDecorations: env.evalDecorations,
                range: data.range,
                text: response,
            });
            decor.removeRange({
                decorations: env.evalErrorDecorations,
                decoration: env.evalErrorDecoration,
                editor: data.editor,
                range: data.range,
            });
        }
    } catch (err) {
        env.outChannel.appendLine(
            `Error sending ${c.cfgSection}.${data.vscodeCommand}: ${
                (err as Error).message
            }`
        );
    }
}

With that we should be able to compare the PATHs for the two REPLs.

migraine-user commented 3 months ago

Completion error: spawn scheme ENOENT

says that completions don't work either.

Is scheme the correct name of your Chez executable? But on the other hand, it works as interactive REPL. Is the scheme command in a special directory, which isn't part of the "normal" Linux PATH?

Can you please post the output of printenv PATH in the Console of VS Code? And add the output of the PATH to the program, by adding

env.outChannel.appendLine(`PATH: ${process.env.PATH}`);

To the beginning of evalSexp, so that it now is

async function evalSexp(
    env: h.Env,
    data: {
        editor: vscode.TextEditor;
        exp: {
            sexp: string;
            startLine: number;
            startCol: number;
        };
        range: vscode.Range;
        vscodeCommand: string;
    }
): Promise<void> {
    env.outChannel.appendLine(`PATH: ${process.env.PATH}`);
    try {
        const out = await runREPLCommand(
            env.config,
            data.editor.document,
            data.exp.sexp
        );
        env.outChannel.appendLine(
            `Sent ${data.exp.sexp} to REPL using command ${c.cfgSection}.${data.vscodeCommand}`
        );
        if (out.stderr) {
            const errMsg = out.stderr.trim();
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalErrorDecoration,
                evalDecorations: env.evalErrorDecorations,
                range: data.range,
                text: errMsg,
            });
            decor.removeRange({
                decorations: env.evalDecorations,
                decoration: env.evalDecoration,
                editor: data.editor,
                range: data.range,
            });
        } else if (out.error) {
            const errMsg = out.error.trim();
            env.outChannel.appendLine(
                `Error sending ${c.cfgSection}.${data.vscodeCommand}: ${errMsg}`
            );
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalErrorDecoration,
                evalDecorations: env.evalErrorDecorations,
                range: data.range,
                text: errMsg,
            });
            decor.removeRange({
                decorations: env.evalDecorations,
                decoration: env.evalDecoration,
                editor: data.editor,
                range: data.range,
            });
        } else {
            const match = out.stdout
                ? out.stdout.match(matchREPLResponse("(.+?)"))
                : "";
            const response = match ? match[1].trim() : "";
            decor.addEditorDecoration({
                editor: data.editor,
                evalDecoration: env.evalDecoration,
                evalDecorations: env.evalDecorations,
                range: data.range,
                text: response,
            });
            decor.removeRange({
                decorations: env.evalErrorDecorations,
                decoration: env.evalErrorDecoration,
                editor: data.editor,
                range: data.range,
            });
        }
    } catch (err) {
        env.outChannel.appendLine(
            `Error sending ${c.cfgSection}.${data.vscodeCommand}: ${
                (err as Error).message
            }`
        );
    }
}

With that we should be able to compare the PATHs for the two REPLs.

Installing chez from AUR added chez and chez-script in my PATH, and the way it was working originally, chez was aliased to scheme. I've also tried aliasing chez-script to scheme instead, which completely broke the extension. Is there a different executable I should use?

migraine-user commented 3 months ago

Ah, I understand now. I believe the extension does not work with an alias, and I would need to change the name of the executable to scheme. This makes it so that macroexpansion works but not the others since macroexpansion seems to work differently. PATH: /usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl This is the PATH, and the second directory contains chez. It just assumes that chez exists in the PATH, not as an alias in the terminal.

Release-Candidate commented 3 months ago

No, chez or scheme are fine. You can set the name of the executable to use in the settings of Chez Scheme REPL, you could try it with chez instead of the default scheme, the settings name is chezScheme.schemePath. Bildschirmfoto 2024-07-03 um 21 42 12

Release-Candidate commented 3 months ago

Oh, of course. Yes, shell aliases only work if the command is send to a shell - which is the case in the interactive REPL. But spawn does not. So setting the command name to chez in the settings should solve the issue.

migraine-user commented 3 months ago

Thank you for your time. I should have looked at the extension settings closer. It might be helpful to add this in the description of the extension in case someone has a similar problem. I also found a different error while testing this out: image It seems like you cannot use inline evaluation if the file doesn't exist yet. I was not sure if it was intended.

Release-Candidate commented 3 months ago

Actually I've just got the idea to check the Scheme executable at startup and display an error message if it doesn't work.

And you are right, it tries to send the whole file which doesn't work if it hasn't been saved yet.

Anyways, thank you very much for your time and help, without you I wouldn't have a chance to solve the problem! I'm going to make a new version of the extension, so there will be an update in the not too distant future.