Skip to content
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

Deliver full intersection type of a value to the IDE #11583

Merged
merged 12 commits into from
Nov 22, 2024

Conversation

4e6
Copy link
Contributor

@4e6 4e6 commented Nov 18, 2024

Pull Request Description

close #11481

Changelog:

  • update: handle MultiTypeValue results in the execution instrument
  • update: language server protocol supports multi-type values
  • update: GUI uses only the first type of a multi-type value when

Important Notes

GUI uses only the first type of the intersection. See the difference between Integer&Text and Text&Integer:

enso-11481-intersection-types.mp4

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.

@4e6 4e6 added CI: No changelog needed Do not require a changelog entry for this PR. -language-server -gui labels Nov 18, 2024
@4e6 4e6 self-assigned this Nov 18, 2024
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.

The change itself is fine, but it reveals long term unresolved issues:

  • are incompatible changes in the protocol OK?
  • versioning on the protocol is missing
  • duplication of functionality instead of encapsulating it in TypeOfNode

@@ -195,7 +195,7 @@ export interface ExpressionUpdate {
/** The id of updated expression. */
expressionId: ExpressionId
/** The updated type of the expression. */
type?: string
type: string[]
Copy link
Member

Choose a reason for hiding this comment

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

This is an incompatible message change. Single values used to be represented as "string" and now they will be [ "string" ]. Are we sure we don't need compatibility?

@@ -367,7 +367,7 @@ interface ExpressionUpdate {
/** The id of updated expression. */
expressionId: ExpressionId;
/** The updated type of the expression. */
type?: string;
type: string[];
Copy link
Member

Choose a reason for hiding this comment

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

I feel incompatible changes should be versioned and documented. We should:

  • increase the version of the protocol
  • describe what change has happened and why it is incompatible

Sure, I know we have no version of the protocol. However I asked for it a year ago. Moreover recently there were complains about incompatibilities between cloud/IDE and the conclusion was: we should at least detect the incompatibilities by versioning our protocols.

@@ -198,14 +198,14 @@ object ProgramExecutionSupport {
val notExecuted =
methodCallsCache.getNotExecuted(executionFrame.cache.getCalls)
notExecuted.forEach { expressionId =>
val expressionType = executionFrame.cache.getType(expressionId)
val expressionCall = executionFrame.cache.getCall(expressionId)
val expressionTypes = executionFrame.cache.getType(expressionId)
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't the getType method be renamed to getTypes?

@@ -367,7 +367,7 @@ interface ExpressionUpdate {
/** The id of updated expression. */
expressionId: ExpressionId;
/** The updated type of the expression. */
Copy link
Contributor

Choose a reason for hiding this comment

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

The current docs are not clear about some details of the protocol. An empty array seems to be treated specially; judging from the implementation, it looks like:

  • When the status is Pending, an empty array can indicate that the type has not been determined yet.
  • When the status is not Pending, an empty array indicates that no specific type is known for the value--maybe this can happen either if the type is known to be Any. Can this also happen if the type could not be determined?

Are these updates incremental? It's not clear whether in the pending state [] might be sent to indicate "no change", or every update will contain all currently-known type information even if it hasn't changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated the docs. The logic did not change. The array is just a way to encode intersection types

  • [] indicates no type information (previously null)
  • [T] represent a type of the expression (previously T)
  • [T,U] represents an intersection type T & U (previously not supported, probably delivered just as a T type)

Copy link
Collaborator

@hubertp hubertp left a comment

Choose a reason for hiding this comment

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

In this particular case I would agree with Jaroslav that the binary incompatible change this PR introduces might be problematic.
We could have both, type and types, fields be present for the time being at the cost of some duplication. Then GUI could make a switch to support intersection types more gently and we could deprecate (and eventually remove)type.

case msg: Api.ExpressionUpdates if state.isSuggestionUpdatesRunning =>
state.suggestionUpdatesQueue.enqueue(msg)

case Api.ExpressionUpdates(_, updates) =>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this change? Seems rather unrelated. Or is that feature no longer used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, after the component browser is finished, and GUI can handle suggestions itself, we don't need to do this logic anymore

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.

The change in TypeOfNode isn't correct and fails on Truffle asserts. I'll prepare an alternative approach.

@@ -75,6 +75,11 @@ Object doWarning(WithWarnings value, @Cached TypeOfNode withoutWarning) {
return withoutWarning.execute(value.getValue());
}

@Specialization
Object doEnsoMultiValue(EnsoMultiValue value) {
return value.allTypes();
Copy link
Member

@JaroslavTulach JaroslavTulach Nov 21, 2024

Choose a reason for hiding this comment

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

Hello Dmitry,
thanks for trying to implement my request to concentrate the logic of obtaining a type array into TypeOfNode in 86bfb98, but this cannot work - the Object here means: any valid interop value and Java arrays aren't such values.

Such a code change isn't likely to pass the Truffle assert checks as for example this failure indicates

The change has to be done differently. I'll prepare a PR for review:

With 87e738b there is findAllTypes method that provides all the Type[] associated with a value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can wrap the result in EnsoObject

Copy link
Member

Choose a reason for hiding this comment

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

I can wrap the result in EnsoObject

Interesting idea, yes that would fix the Truffle assertion errors:

  • use ArrayLikeHelpers.wrapEnsoObjects
  • let's see what other failures we get

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess, I should wait for #11618

Copy link
Member

Choose a reason for hiding this comment

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

@somebody1234
Copy link
Contributor

mockSuggestions.json probably needs to be regenerated here (@farmaazon?)

@4e6
Copy link
Contributor Author

4e6 commented Nov 21, 2024

@somebody1234 it does not change the suggestion interface. This change is only about the expression update.

Copy link

github-actions bot commented Nov 22, 2024

🧪 Storybook is successfully deployed!

📊 Dashboard:

@4e6 4e6 requested a review from JaroslavTulach November 22, 2024 16:21
}

var typeOfNode = TypeOfNode.getUncached();
Type[] allTypes = value == null ? null : typeOfNode.findAllTypesOrNull(value);
Copy link
Member

Choose a reason for hiding this comment

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

Nice.

@4e6 4e6 added the CI: Ready to merge This PR is eligible for automatic merge label Nov 22, 2024
@mergify mergify bot merged commit 2b9ed57 into develop Nov 22, 2024
55 of 58 checks passed
@mergify mergify bot deleted the wip/db/11481-intersection-type-update branch November 22, 2024 16:41
kazcw added a commit that referenced this pull request Nov 25, 2024
- Update mock data for multi-type expression updates (#11583)
kazcw added a commit that referenced this pull request Nov 25, 2024
- Update mock data for multi-type expression updates (#11583)
kazcw added a commit that referenced this pull request Nov 26, 2024
- Update mock data for multi-type expression updates (#11583)
mergify bot pushed a commit that referenced this pull request Nov 26, 2024
Fix failing integration tests:
- Fix a Vue Teleporter crash that became reachable when the dropdown arrow is displayed more often (#11620).
- Fix a new drag-and-drop test that didn't work in CI.
- Update mock data for multi-type expression updates (#11583).

# Important Notes
- The new `ConditionalTeleport` component should be used for any `Teleport` that uses the `disabled` prop and has a `to` that isn't always a valid teleportation target.
hubertp pushed a commit that referenced this pull request Nov 26, 2024
Fix failing integration tests:
- Fix a Vue Teleporter crash that became reachable when the dropdown arrow is displayed more often (#11620).
- Fix a new drag-and-drop test that didn't work in CI.
- Update mock data for multi-type expression updates (#11583).

# Important Notes
- The new `ConditionalTeleport` component should be used for any `Teleport` that uses the `disabled` prop and has a `to` that isn't always a valid teleportation target.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
-gui -language-server CI: No changelog needed Do not require a changelog entry for this PR. CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deliver full intersection type of a value to the IDE
5 participants