Skip to content

Document return type in the Language Server API #13530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

4e6
Copy link
Contributor

@4e6 4e6 commented Jul 17, 2025

Pull Request Description

close #13268

Changelog:

  • update: clarify the return type definition

Important Notes

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    TypeScript,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • Unit tests have been written where possible.
  • If meaningful changes were made to logic or tests affecting Enso Cloud integration in the libraries,
    or the Snowflake database integration, a run of the Extra Tests has been scheduled.
    • If applicable, it is suggested to paste a link to a successful run of the Extra Tests.

@4e6 4e6 self-assigned this Jul 17, 2025
@4e6 4e6 added CI: No changelog needed Do not require a changelog entry for this PR. -language-server labels Jul 17, 2025
@4e6 4e6 requested review from JaroslavTulach and vitvakatu July 17, 2025 08:27
Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

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

  • I'd like to see documentation or even a test to verify Typename
  • preferably a code example showing how to turn it into AST on both sides
  • in JVM as well as in TypeScript

@@ -372,7 +372,7 @@ interface ExpressionUpdate {
*
* Possible values:
* - empty array indicates no type information for this expression
* - array with a single value contains a value of this expression
* - array with a single value contains a qualified type name of this expression
* - array with multiple values represents an intersetion type
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* - array with multiple values represents an intersetion type
* - array with multiple values represents an intersection type

each array element contains fully qualified type name, right?

* Type representation.
*
* - For a simple type it contains a qualified type name
* - For complex types it contains a text representation of this type (i.e. how it is defined in the code)
Copy link
Member

Choose a reason for hiding this comment

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

  • does the text represent a valid Enso type specification?
  • can it be parsed?
  • how can one parse the text value in JVM?
  • how can one parse the text value in TypeScript?

Ccing @kazcw with following motivation:

  • there is a shared parser between JVM and JavaScript VM
  • that parser is the ultimate way to turn an Enso code into AST
  • a Typename is an Enso code, right?
  • thus there should be a way to turn that code into AST using that parser, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

I understand what a “qualified type name” is, but I don’t understand what a “text representation of this type” is.

That was actually a rationale for the whole task — we are pretty confident when working with qualified names in suggestion database fields, and we usually see qualified names there. For working with qualified names, GUI mainly uses simple string parsing techniques like “split by . and group resulting segments.” However, the possibility of seeing something different from a qualified name requires more careful parsing, and, more importantly, business logic and abstractions for further interpretation.

@JaroslavTulach raised good questions. I would like to see a description of this Typename format in terms of AST nodes, although it might be overly generic for practical purposes. It wouldn’t help to have “well, any parseable Enso expression can be there”.

Also, I understand that “either simple type or a complex type” is an easy formulation, but I’m not satisfied with it.

  • Are intersection types considered complex? Or is it always represented as an array of Typenames? Why are intersection types described as string[], not Typename[]? (see the other comment)
  • Generic types are, of course, complex, right? I heard that generic types are partially supported, so in protocol messages, Vector Integer is returned as Vector. Is this correct?
  • Are Union types (is it a correct name for Integer | Boolean?) complex? Can the parentType field be a union, or is it always reported as a single type? What about selfType and returnType?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Anything other than a simple type (represented as a qualified name) is considered a complex type that can be an arbitrary Enso expression. To create a meaningful type representation, we could first decide which types can be useful for IDE, and then create a Typescript encoding (structure) for it.

Copy link
Member

Choose a reason for hiding this comment

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

  • @4e6, in the Friday discussion you pointed out that proper representation of a type in the engine is ir.Expression.
  • I'd like to disagree with you on that, @4e6, but ...
  • given Enso tried to support dependent types I cannot disagree
  • hence I have to accept your claim that proper representation is ir.Expression
  • IDE doesn't have "IR structures", but they do have similar Ast structures
  • thus proper representation on the IDE side has to be some Ast structure
  • both of these structures (IR as well as Ast) are created by parsing

create a meaningful type representation, we could first decide which types can be useful for IDE, and then create a Typescript encoding (structure) for it

  • please stop inventing new JSON representations of types
  • and just tell us how to parse the Typename strings!
  • (assuming Typename string is generated properly and can be parsed)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ir.Expression is how the type is currently represented in IR. Whether it is a proper encoding or not is a subject to discussion. And because the Typename string is an expression, you should be able to parse it by Enso parser.

Copy link
Member

@JaroslavTulach JaroslavTulach Jul 18, 2025

Choose a reason for hiding this comment

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

should be

  • "Should" isn't really a word that belongs into a specification
  • especially if you mean "should work, but I don't know, I haven't tried"
  • and "you can try it yourself and see - it should work somehow"

able to parse it by Enso parser.

  • Great. Time to demonstrate that!
  • Can we have a code snippet that:
    • Shows how to parse the string?
    • assert that values sent via language server protocol can be parsed that way?
  • Can we have a code snippet in TypeScript that:
    • Shows how to parse the string on the IDE side?

When @kazcw was working on the Rust Enso parser, he created a test that scans all the distribution/**.enso sources and parses them all. That way he could be sure that all code statements that we are using can be parsed by his new parser. I have no idea where and how the Typename is composed, but could we do something similar? Search the code base, construct the Typenames and parse them the way documentation describes they must be parsable?

@@ -372,7 +372,7 @@ interface ExpressionUpdate {
*
* Possible values:
* - empty array indicates no type information for this expression
* - array with a single value contains a value of this expression
* - array with a single value contains a qualified type name of this expression
* - array with multiple values represents an intersetion type
*/
type: string[];
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is it string[], not Typename[]?

* Type representation.
*
* - For a simple type it contains a qualified type name
* - For complex types it contains a text representation of this type (i.e. how it is defined in the code)
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand what a “qualified type name” is, but I don’t understand what a “text representation of this type” is.

That was actually a rationale for the whole task — we are pretty confident when working with qualified names in suggestion database fields, and we usually see qualified names there. For working with qualified names, GUI mainly uses simple string parsing techniques like “split by . and group resulting segments.” However, the possibility of seeing something different from a qualified name requires more careful parsing, and, more importantly, business logic and abstractions for further interpretation.

@JaroslavTulach raised good questions. I would like to see a description of this Typename format in terms of AST nodes, although it might be overly generic for practical purposes. It wouldn’t help to have “well, any parseable Enso expression can be there”.

Also, I understand that “either simple type or a complex type” is an easy formulation, but I’m not satisfied with it.

  • Are intersection types considered complex? Or is it always represented as an array of Typenames? Why are intersection types described as string[], not Typename[]? (see the other comment)
  • Generic types are, of course, complex, right? I heard that generic types are partially supported, so in protocol messages, Vector Integer is returned as Vector. Is this correct?
  • Are Union types (is it a correct name for Integer | Boolean?) complex? Can the parentType field be a union, or is it always reported as a single type? What about selfType and returnType?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
-language-server CI: No changelog needed Do not require a changelog entry for this PR.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Improve description of LS protocol types in documentation.
3 participants