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

fix(workspace): Dendron will try to parse non-dendron files in onFirstOpen #2405

Merged
merged 10 commits into from
Feb 15, 2022

Conversation

kevinslin
Copy link
Member

@kevinslin kevinslin commented Feb 12, 2022

This commit makes the following changes:

  • onFirstOpen should only track files in the workspace
  • note specific operations (eg. moving cursor past frontmatter) should only happen for dendron notes
  • adds two new methods to IDendronExtension (activateWatchers and deactivate)

Before, opening a big json file (eg. Dendron Logs) would cause vscode to crash because Dendron would try to parse the entire log file.

This commit also introduces two new conventions:

  1. The WorkspaceWatcher is hard to test since methods are private and require a working VSCode workspace to actually trigger (which we do not have access to in tests).
    Some solutions that were explored:
  • ad-hoc dependency injection: resulted in too many code changes, we're better off actually implementing DI properly using one of the frameworks: https://blog.logrocket.com/top-five-typescript-dependency-injection-containers but out of scope for this task
  • making private variables public - not great since they were private for a reason
  • introduce the __DO_NOT_USE_IN_PROD_exposePropsForTesting method/convention to expose internal workspace state for testing

We went with the last option (will update in [[Testing|dendron://dendron.docs/dev.process.qa.test]] after the PR)

  1. During testing, we often do typecasts of the form foo!.bar or use @ts-ignore. This isn't great. In the future, we want to enable strict type checks and dis-allow type assertions.
    To make it easier to get to this future, this PR introduces the UNSAFE_getWorkspaceWatcherPropsForTesting convention: everytime you need to type cast, wrap it in a function.
    This groups all unsafe assertions in one place (which we can then add to a special unsafe file which we can ignore for strict type checking)

circular dependencies:

  • before: 52
  • after: 52

Export

Dendron Extended PR Checklist

Code

Basics

  • code should follow Code Conventions
  • circular dependency check: make sure your code is not introducing new circular dependencies in plugin-core. See Avoiding Circular Dependencies.
  • [~] sticking to existing conventions instead of creating new ones
    • this introduces some new testing conventions

Extended

  • General
    • check whether code be simplified
    • check if similar function already exist in the codebase. if so, can it be re-used?
    • check if this change adversely impact performance
  • Operations
    • when shipping this change, will it just work or will it introduce additional operational overhead due to complicated interface or known bugs?
  • Architecture
    • check if code is introducing changes on a foundational class or interface. if so, call for design review if needed

Instrumentation

Basics

  • [~] if you are adding analytics related changes, make sure the Telemetry docs are updated

Extended

Tests

Basics

Extended

NA

Docs

Basics

  • [~] if your change reflects documentation changes, also submit a PR to dendron-site and mention the doc PR link in your current PR

Basics

  • [B] does this change introduce a new or better way of doing things that others need to be aware of? if so, an async should be created and a process added in Development or Packages
  • pending successful code review

Close the Loop

Basics

Extended

  • [~] is this a developer BREAKING change? if another person cloning from this branch will need to adjust their dependencies or mental model of the architecture, then it is. if this is the case, make sure this is communicated according to Close Loop

packages/plugin-core/src/WorkspaceWatcher.ts Show resolved Hide resolved

// if markdown file, does it have frontmatter?
// this is a rough heuristic
return fs.readFileSync(fpath, { encoding: "utf8" }).startsWith("---");
Copy link
Contributor

Choose a reason for hiding this comment

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

should we prefer async versions for perf reasons?

Copy link
Member Author

Choose a reason for hiding this comment

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

changed it to async. something I do worry about is that its not immediately clear when functions are sync/async and we already have places in the code where we will either await a non-async function or fail to await an async function.

we should look into either:

  • adding a convention (eg. isDendronNoteAsync) to be explicit about the return
  • add stricter linting rules about asyncs

Copy link
Member Author

Choose a reason for hiding this comment

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

added a task to oncall backlog -> [[Better Tooling around Async Functions|dendron://private/task.2022.02.14.better-tooling-around-async-functions]]

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm for an async convention, but additionally, how about explicitly stating its return value? isDendronNote(...): Promise<string> {} / async isDendronNote(...): string

@jonathanyeung
Copy link
Contributor

ad-hoc dependency injection: resulted in too many code changes, we're better off actually implementing DI properly using one of the frameworks: https://blog.logrocket.com/top-five-typescript-dependency-injection-containers but out of scope for this task

Yeah, I'm for this - but obviously, for it to work it'll take a lot more refactoring of our existing classes. Generally I think DI libraries help once your injected objects become more complex (multi-tier injections). Where we're at today with the circ dep refactoring I haven't had to inject a multi-tiered object yet, but when we do I think it'll make sense to adopt a library such as TSyringe.

);
const { onFirstOpen } =
UNSAFE_getWorkspaceWatcherPropsForTesting(ext);
expect(await onFirstOpen(editor)).toBeFalsy();
Copy link
Contributor

Choose a reason for hiding this comment

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

minor nitpick, but this could also check that foldFrontmatter is not called since the main issue we're trying to fix is that Dendron tries to fold the frontmatter in non-note files. Or that could go into a different test if we want to keep the concerns of each test separate.

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, that would be a better test. unfortunately not sure how to do this since in order to spy on a method, you need to either 1) pass in an object and the method or 2) spy on the method and inject the method

  1. isn't feasible because the method is private so we can't spy on the object
  2. isn't feasible because we don't have dependency inejction so we can't make onFirstOpen call a spied method

https://sinonjs.org/releases/latest/spies/

Copy link
Contributor

@SeriousBug SeriousBug left a comment

Choose a reason for hiding this comment

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

Left a comment about a possible improvement.

packages/engine-server/src/workspace/utils.ts Outdated Show resolved Hide resolved
@kevinslin kevinslin merged commit d913a7f into master Feb 15, 2022
@kevinslin kevinslin deleted the fix/dendron-hang-on-large-json branch February 15, 2022 02:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants