-
Notifications
You must be signed in to change notification settings - Fork 334
Module Store #14092
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
base: develop
Are you sure you want to change the base?
Module Store #14092
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned during the daily, I think it would be nice to have some high-level docs clarifying the responsibilities of the module store vs. the graph store.
Besides that, I have some thoughts that may be considered non-blocking / ideas for related work (as this PR seems at risk of merge conflicts as it is):
- We have two interfaces to
useCurrentProject
,ref
andstoresRefs
--it seems we usually usestoresRefs
, and in the few cases we use theref
it seems we could just as well usestoresRefs
. Maybe we could simplify this? - In general, we often accept
ToValue
arguments to make APIs flexible to use; however, we are now accepting stores as arguments in many places. Typically, the stores are alreadyRef
s at the call site. If we type them asRef
s in the argument lists, we could access them with the.value
syntax, which IMO is more readable. - We are using
module
for a few different things--there ismodule: DistributedModule
in theProjectStore
,module
as the name of theModuleStore
, and sometimes we use it as the name of aMutableModule
; and of course it has a meaning in JS. I don't have a better alternative to propose right now; maybe we should just rename some of these things if we come up with anything later. - You mentioned that we sometimes commit the same
MutableModule
more than once--I think we should detect this and print a warning; not necessarily in this PR though.
}) | ||
|
||
const visualizationData = project.useVisualizationData(visualizationConfig) | ||
// TODO[ao]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
directInteraction: true, | ||
}) | ||
} | ||
module.value.edit((edit) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be a good time to move the side effect here from the setter to a watcher
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it's nothing wrong with side effects in setters?
widgetRegistry: computed(() => ref.value?.widgetRegistry), | ||
} satisfies ToRefs<{ [K in keyof OpenedProject]: OpenedProject[K] | undefined }>, | ||
store: computed(() => ref.value.store), | ||
names: computed(() => ref.value.names), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're changing this, I've always thought names
an odd name for the store that holds project names. A lot of things have names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's because I assumed usages project.names
, but as we use more storeRefs than refs, this should be projectNames
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
project.names
is sort of a pun, as project
does double duty as the "current project" and the "project name" store associated with the current project.
(app) => 'portId' in app.argument && app.argument.portId === origin, | ||
) | ||
const argApp = applications[argAppIndex] | ||
const f = (edit: Ast.MutableModule) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the usage of this function occurs many lines from its definition, I think a descriptive name would be helpful
export type ModuleStore = ReturnType<typeof createModuleStore> | ||
|
||
/** | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docs?
function addMissingImportsDisregardConflicts( | ||
edit: MutableModule, | ||
imports: RequiredImport[], | ||
existingImports?: AbstractImport[] | undefined, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could remove existingImports
and just always call analyzeImports
. It looks like the argument is only used to avoid having to do the analysis twice, but the analysis shouldn't be an expensive operation so there's no need for this API complication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead, I removed addMissingImportsDisregardConflicts from public API.
|
||
const importsToAdd = filterOutRedundantImports(existingImports_, imports) | ||
if (!importsToAdd.length) return | ||
addImports(edit.getVersion(topLevel), importsToAdd, projectNames) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addImports(edit.getVersion(topLevel), importsToAdd, projectNames) | |
addImports(topLevel, importsToAdd, projectNames) |
edit.replaceValue(origin, ast) | ||
} else if (typeof value === 'string') { | ||
edit.tryGet(origin)?.syncToCode(value) | ||
const f = (edit: Ast.MutableModule) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another long f
function
const update = this.observeEvents(events, tryAsOrigin(transaction.origin)) | ||
for (const observer of this.updateObservers ?? []) observer(update) | ||
} catch (err) { | ||
console.error('AST observer caught an exception', err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we catch an error here, some type of misbehaviour is likely. If we try to continue, I think we should at least have a toast, something like "An internal error has occurred; reopening the project is recommended."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we “reopen” the project ourselves in this case? It does not make sense to transfer this decision to the user, who doesn’t understand what is happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we “reopen” the project ourselves in this case? It does not make sense to transfer this decision to the user, who doesn’t understand what is happening.
Probably, but not in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just removed the try-catch for now. Actually, the AST state should not be broken because of throwing oberver, in this case it was broken because of something else.
I will add a task for tracking crashes in ProjectView.
Co-authored-by: Keziah Wesley <[email protected]>
Pull Request Description
Part of prerequisites for testing #13741 properly
$/providers/openedProjects
because they don't need to be bound to project-view only.useXStore
withuseCurrentProject
Important Notes
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
[ ] Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.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.