cucumber / monaco

Configure Monaco editor to use cucumber-language-service
MIT License
16 stars 4 forks source link

Tree-Sitter resolution errors using NodeParserAdapter in React project. #55

Closed Summersby95 closed 1 year ago

Summersby95 commented 2 years ago

👓 What did you see?

I'm trying to use the Monaco editor library in a React project which uses tree-sitter for Node ParserAdapter but when I'm getting a bunch of resolve errors in the tree-sitter when I do this. I'm importing the NodeParserAdapter, not the WasmParserAdapter from the cucumber/language-service as we aren't using WebAssembly in our project.

Environment: Node v16.17.1 (Docker Image 16.17)

Error Log:

[0]
[0] Search for the keywords to learn more about each warning.
[0] To ignore, add // eslint-disable-next-line to the line before.
[0]
[0] WARNING in ./node_modules/tree-sitter-c-sharp/bindings/node/index.js 2:2-77
[0] Module not found: Error: Can't resolve '../../build/Release/tree_sitter_c_sharp_binding' in '/usr/src/my_project/node_modules/tree-sitter-c-sharp/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-c-sharp/bindings/node/index.js 9:4-77
[0] Module not found: Error: Can't resolve '../../build/Debug/tree_sitter_c_sharp_binding' in '/usr/src/my_project/node_modules/tree-sitter-c-sharp/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-java/bindings/node/index.js 2:2-74
[0] Module not found: Error: Can't resolve '../../build/Release/tree_sitter_java_binding' 
in '/usr/src/my_project/node_modules/tree-sitter-java/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-java/bindings/node/index.js 9:4-74
[0] Module not found: Error: Can't resolve '../../build/Debug/tree_sitter_java_binding' in '/usr/src/my_project/node_modules/tree-sitter-java/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-php/index.js 2:2-69
[0] Module not found: Error: Can't resolve './build/Release/tree_sitter_php_binding' in '/usr/src/my_project/node_modules/tree-sitter-php'
[0]
[0] WARNING in ./node_modules/tree-sitter-php/index.js 5:4-69
[0] Module not found: Error: Can't resolve './build/Debug/tree_sitter_php_binding' in '/usr/src/my_project/node_modules/tree-sitter-php'
[0]
[0] WARNING in ./node_modules/tree-sitter-python/bindings/node/index.js 2:2-76
[0] Module not found: Error: Can't resolve '../../build/Release/tree_sitter_python_binding' in '/usr/src/my_project/node_modules/tree-sitter-python/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-python/bindings/node/index.js 9:4-76
[0] Module not found: Error: Can't resolve '../../build/Debug/tree_sitter_python_binding' 
in '/usr/src/my_project/node_modules/tree-sitter-python/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-ruby/bindings/node/index.js 2:2-74
[0] Module not found: Error: Can't resolve '../../build/Release/tree_sitter_ruby_binding' 
in '/usr/src/my_project/node_modules/tree-sitter-ruby/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-ruby/bindings/node/index.js 9:4-74
[0] Module not found: Error: Can't resolve '../../build/Debug/tree_sitter_ruby_binding' in '/usr/src/my_project/node_modules/tree-sitter-ruby/bindings/node'
[0]
[0] WARNING in ./node_modules/tree-sitter-typescript/bindings/node/index.js 2:2-80        
[0] Module not found: Error: Can't resolve '../../build/Release/tree_sitter_typescript_binding' in '/usr/src/my_project/node_modules/tree-sitter-typescript/bindings/node'      
[0]
[0] WARNING in ./node_modules/tree-sitter-typescript/bindings/node/index.js 9:4-80        
[0] Module not found: Error: Can't resolve '../../build/Debug/tree_sitter_typescript_binding' in '/usr/src/my_project/node_modules/tree-sitter-typescript/bindings/node'        
[0]
[0] WARNING in ./node_modules/tree-sitter/index.js 4:12-66
[0] Module not found: Error: Can't resolve './build/Release/tree_sitter_runtime_binding' in '/usr/src/my_project/node_modules/tree-sitter'
[0]
[0] WARNING in ./node_modules/tree-sitter/index.js 7:14-66
[0] Module not found: Error: Can't resolve './build/Debug/tree_sitter_runtime_binding' in 
'/usr/src/my_project/node_modules/tree-sitter'
[0]
[0] webpack compiled with 14 warnings

Tree Sitter and the other tree-sitter-c-sharp, tree-sitter-java etc are all installed and in the node_modules directory of the project.

tree-sitter
tree-sitter-c-sharp
tree-sitter-cli
tree-sitter-java
tree-sitter-php
tree-sitter-python
tree-sitter-ruby
tree-sitter-typescript

And when I look in the tree-sitter/build/Release I can see the tree_sitter_runtime_binding.node file

root@abc123:/usr/src/my_project/node_modules/tree-sitter/build/Release# ls
obj.target  tree_sitter.a  tree_sitter_runtime_binding.node

So why can't tree-sitter resolve it?

Have tried Node 18, that didn't work, tried running the build command directly from the node_modules/tree-sitter directory, didn't work, have tried installing tree-sitter in a new folder on it's own and getting the same error. Any help much appreciated.

✅ What did you expect to see?

The tree-sitter package to resolve correctly and for the Monaco editor to work with the @cucumber/monaco library.

📦 Which tool/library version are you using?

+-- @cucumber/monaco@0.11.0
| +-- @cucumber/language-service@0.32.0
| | +-- @cucumber/cucumber-expressions@16.0.0 
| | +-- @cucumber/gherkin-utils@8.0.0 
| | +-- @cucumber/gherkin@24.0.0 
| | +-- @cucumber/messages@19.1.4 
| | +-- @types/js-search@1.4.0 
| | +-- @types/mustache@4.2.1 
| | +-- fuse.js@6.6.2 
| | +-- js-search@2.0.0 
| | +-- mustache@4.2.0 
| | +-- tree-sitter-c-sharp@0.19.1 
| | +-- tree-sitter-cli@0.20.6
| | +-- tree-sitter-java@0.19.1 
| | +-- tree-sitter-php@0.19.0 
| | +-- tree-sitter-python@0.20.1 
| | +-- tree-sitter-ruby@0.19.0 
| | +-- tree-sitter-typescript@0.20.1 
| | +-- tree-sitter@0.20.0 
| | +-- vscode-languageserver-types@3.17.2 
| | `-- web-tree-sitter@0.20.5
| +-- monaco-editor@0.33.0
| `-- vscode-languageserver-types@3.17.2 

Node.js 16.17.1, tried with later versions of Node but to no success. React 18.2

🔬 How could we reproduce it?

Steps to reproduce the behavior:

  1. Start a node:16.17 Docker container
  2. Create a React project using the Create React App template
  3. Install the Monaco editor library and @cucumber/monaco library
  4. Create a TestEditor.jsx file
  5. Import the NodeParserAdapter into the file
  6. Bug should reproduce

Below is the code snippet I'm trying to run.

import React from 'react'
// Import the components
import VerticalNav from '../../components/navbar/VerticalNav'
import HorizontalNav from '../../components/navbar/HorizontalNav'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'

import MonacoEditor from '@monaco-editor/react'
import { configureMonaco } from '@cucumber/monaco'
import { ParameterTypeRegistry } from '@cucumber/cucumber-expressions'
import {
    buildSuggestions,
    ExpressionBuilder,
    jsSearchIndex,
} from '@cucumber/language-service'
import { NodeParserAdapter } from '@cucumber/language-service/node'
import { render } from 'react-dom'

const value = `@foo
Feature: Hello
Scenario: Hi
  Given I have 58 cukes in my belly
  And this is an undefined step
    | some | poorly |
    | formatted | table |
`

async function Editor() {
    monaco.languages.register({ id: 'typescript' })
    const sources = [
        {
            languageName: 'java',
            uri: 'file:///tmp/StepDefinitions.java',
            content: `class StepDefinitions {
                @Given("I have {int} cukes in my belly"  )
                void method1() {
                }

                @Given("there are {int} blind mice")
                void method2() {
                }

                @Given("there is/are some/none/1 apple(s)")
                void method2() {
                }
            }
            `,
        },
    ]
    const adapter = new NodeParserAdapter('.')
    await adapter.init()
    const expressionBuilder = new ExpressionBuilder(adapter)

    const { expressionLinks } = expressionBuilder.build(sources, [])
    const expressions = expressionLinks.map((link) => link.expression)

    const registry = new ParameterTypeRegistry()
    const docs = buildSuggestions(
        registry,
        [
            'I have 42 cukes in my belly',
            'I have 96 cukes in my belly',
            'there are 38 blind mice',
        ],
        expressions,
    )
    const index = jsSearchIndex(docs)

    return configureMonaco(monaco, index, expressions)
}

export default function EditorElement() {
    const options = {
        value,
        language: 'gherkin',
        theme: 'vs-dark',
        // semantic tokens provider is disabled by default
        'semanticHighlighting.enabled': true,
    }

    Editor()
        .then((configureEditor) => {
            // @ts-ignore
            console.log('Hello World')
            render(
                <MonacoEditor
                    height="90vh"
                    options={options}
                    className="editor"
                    configure={configureEditor}
                />,
                document.getElementById('editor'),
            )
        })
        .catch((err) => console.error(err.stack))

    return (
        <>
            <div className="flex">
                <VerticalNav />
                <div className="h-screen flex-1">
                    <HorizontalNav />
                    <div className="pt-9 w-[90%] m-auto">
                        <div id="editor"></div>
                    </div>
                </div>
            </div>
        </>
    )
}

I tried following the example in the try folder, just replacing the WasmParserAdapter with the NodeParserAdapter but then I couldn't get any further with the resolve errors.

Any advice or help is much appreciated

📚 Any additional context?

Think I've gone through everything.

aslakhellesoy commented 2 years ago

Hi @Summersby95

The NodeParserAdapter cannot run in a browser as it requires a Node.js runtime. It looks like we've made some mistakes in the packaging of NodeParserAdapter, but even if we fixed that, it would never run in the browser.

I'm importing the NodeParserAdapter, not the WasmParserAdapter from the cucumber/language-service as we aren't using WebAssembly in our project.

You don't need to be using WebAssembly in your project. The Wasm code (compiled tree-sitter modules) are handled in an encapsulated way by the WasmParserAdapter. All you need to do is to make the .wasm files available to be downloaded.