Skip to content

Commit a1711e0

Browse files
authored
Merge branch 'microsoft:main' into main
2 parents 1f1fba0 + da543af commit a1711e0

File tree

718 files changed

+29482
-13536
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

718 files changed

+29482
-13536
lines changed

.eslint-ignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
**/src/typings/**/*.d.ts
3434
**/src/vs/*/**/*.d.ts
3535
**/src/vs/base/test/common/filters.perf.data.js
36-
**/src/vs/loader.js
3736
**/test/unit/assert.js
3837
**/test/automation/out/**
3938
**/typings/**

.github/copilot-instructions.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,6 @@ function f(x: number, y: string): void { }
137137
- When adding file watching, prefer correlated file watchers (via fileService.createWatcher) to shared ones.
138138
- When adding tooltips to UI elements, prefer the use of IHoverService service.
139139
- Do not duplicate code. Always look for existing utility functions, helpers, or patterns in the codebase before implementing new functionality. Reuse and extend existing code whenever possible.
140+
141+
## Learnings
142+
- Minimize the amount of assertions in tests. Prefer one snapshot-style `assert.deepStrictEqual` over multiple precise assertions, as they are much more difficult to understand and to update.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
applyTo: '**/chat/**'
3+
description: Chat feature area coding guidelines
4+
---
5+
6+
## Adding chat/AI-related features
7+
8+
- When adding a new chat/AI feature like a new surface where chat or agents appear, a new AI command, etc, these features must not show up for users when they've disabled AI features. The best way to do this is to gate the feature on the context key `ChatContextKeys.enabled` via a when clause.
9+
- When doing a code review for code that adds an AI feature, please ensure that the feature is properly gated.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
applyTo: '**/interactive/**'
3+
description: Architecture documentation for VS Code interactive window component
4+
---
5+
6+
# Interactive Window
7+
8+
The interactive window component enables extensions to offer REPL like experience to its users. VS Code provides the user interface and extensions provide the execution environment, code completions, execution results rendering and so on.
9+
10+
The interactive window consists of notebook editor at the top and regular monaco editor at the bottom of the viewport. Extensions can extend the interactive window by leveraging the notebook editor API and text editor/document APIs:
11+
12+
* Extensions register notebook controllers for the notebook document in the interactive window through `vscode.notebooks.createNotebookController`. The notebook document has a special notebook view type `interactive`, which is contributed by the core instead of extensions. The registered notebook controller is responsible for execution.
13+
* Extensions register auto complete provider for the bottom text editor through `vscode.languages.registerCompletionItemProvider`. The resource scheme for the text editor is `interactive-input` and the language used in the editor is determined by the notebook controller contributed by extensions.
14+
15+
Users can type in code in the text editor and after users pressing `Shift+Enter`, we will insert a new code cell into the notebook document with the content from the text editor. Then we will request execution for the newly inserted cell. The notebook controller will handle the execution just like it's in a normal notebook editor.
16+
17+
## Interactive Window Registration
18+
19+
Registering a new editor type in the workbench consists of two steps:
20+
21+
* Register an editor input factory which is responsible for resolving resources with given `glob` patterns. Here we register an `InteractiveEditorInput` for all resources with `vscode-interactive` scheme.
22+
* Register an editor pane factory for the given editor input type. Here we register `InteractiveEditor` for our own editor input `InteractiveEditorInput`.
23+
24+
The workbench editor service is not aware of how models are resolved in `EditorInput`, neither how `EditorPane`s are rendered. It only cares about the common states and events on `EditorInput` or `EditorPane`, i.e., display name, capabilities (editable), content change, dirty state change. It's `EditorInput`/`EditorPane`'s responsibility to provide the right info and updates to the editor service. One major difference between Interactive Editor and other editor panes is Interactive Window is never dirty so users never see a dot on the editor title bar.
25+
26+
![Editor Registration](./resources/interactive/interactive.editor.drawio.svg)
27+
28+
## Interactive Window Editor Model Resolution
29+
30+
The `Interactive.open` command will manually create an `InteractiveEditorInput` specific for the Interactive Window and resolving that Input will go through the following workflow:
31+
32+
The `INotebookEditorModelResolverService` is used to resolve the notebook model. The `InteractiveEditorInput` wraps a `NotebookEditorInput` for the notebook document and manages a separate text model for the input editor.
33+
34+
When the notebook model is resolved, the `INotebookEditorModelResolverService` uses the working copy infrastructure to create a `IResolvedNotebookEditorModel`. The content is passed through a `NotebookSerializer` from the `INotebookService` to construct a `NotebookTextModel`.
35+
36+
![Model Resolution](./resources/interactive/interactive.model.resolution.drawio.svg)
37+
38+
The `FileSystem` provider that is registered for `vscode-interactive` schema will always return an empty buffer for any read, and will drop all write requests as nothing is stored on disk for Interactive Window resources. The `NotebookSerializer` that is registered for the `interactive` viewtype knows to return an empty notebook data model when it deserializes an empty buffer when the model is being resolved.
39+
40+
Restoring the interactive window happens through the editor serializer (`InteractiveEditorSerializer`), where the notebook data is stored, and can be used to repopulate the `InteractiveEditorInput` without needing to go through the full editor model resolution flow.
41+
42+
## UI/EH Editor/Document Syncing
43+
44+
`EditorInput` is responsible for resolving models for the given resources but in Interactive Window it's much simpler as we are not resolving models ourselves but delegating to Notebook and TextEditor. `InteractiveEditorInput` does the coordination job:
45+
46+
- It wraps a `NotebookEditorInput` via `_notebookEditorInput` for the notebook document (history cells)
47+
- It manages a separate text model via `ITextModelService` for the input editor at the bottom
48+
- The `IInteractiveDocumentService` coordinates between these two parts
49+
- The `IInteractiveHistoryService` manages command history for the input editor
50+
51+
![Architecture](./resources/interactive/interactive.eh.drawio.svg)

.github/instructions/learnings.instructions.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,21 @@ It is a meta-instruction file.
88

99
Structure of learnings:
1010
* Each instruction file has a "Learnings" section.
11-
* Each learning has a counter that indicates how often that learning was useful (initially 1).
1211
* Each learning has a 1-4 sentences description of the learning.
1312

1413
Example:
1514
```markdown
1615
## Learnings
17-
* Prefer `const` over `let` whenever possible (1)
18-
* Avoid `any` type (3)
16+
* Prefer `const` over `let` whenever possible
17+
* Avoid `any` type
1918
```
2019

2120
When the user tells you "learn!", you should:
2221
* extract a learning from the recent conversation
2322
* identify the problem that you created
2423
* identify why it was a problem
2524
* identify how you were told to fix it/how the user fixed it
25+
* reflect over it, maybe it can be generalized? Avoid too specific learnings.
2626
* create a learning (1-4 sentences) from that
2727
* Write this out to the user and reflect over these sentences
2828
* then, add the reflected learning to the "Learnings" section of the most appropriate instruction file
29-
30-
31-
Important: Whenever a learning was really useful, increase the counter!!
32-
When a learning was not useful and just caused more problems, decrease the counter.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
applyTo: '**/notebook/**'
3+
description: Architecture documentation for VS Code notebook and interactive window components
4+
---
5+
6+
# Notebook Architecture
7+
8+
This document describes the internal architecture of VS Code's notebook implementation.
9+
10+
## Model resolution
11+
12+
Notebook model resolution is handled by `NotebookService`. It resolves notebook models from the file system or other sources. The notebook model is a tree of cells, where each cell has a type (code or markdown) and a list of outputs.
13+
14+
## Viewport rendering (virtualization)
15+
16+
The notebook viewport is virtualized to improve performance. Only visible cells are rendered, and cells outside the viewport are recycled. The viewport rendering is handled by `NotebookCellList` which extends `WorkbenchList<CellViewModel>`.
17+
18+
![Viewport Rendering](./resources/notebook/viewport-rendering.drawio.svg)
19+
20+
The rendering has the following steps:
21+
22+
1. **Render Viewport** - Layout/render only the cells that are in the visible viewport
23+
2. **Render Template** - Each cell type has a template (code cell, markdown cell) that is instantiated via `CodeCellRenderer` or `MarkupCellRenderer`
24+
3. **Render Element** - The cell content is rendered into the template
25+
4. **Get Dynamic Height** - Cell height is computed dynamically based on content (editor lines, outputs, etc.)
26+
5. **Cell Parts Lifecycle** - Each cell has lifecycle parts that manage focus, selection, and other state
27+
28+
### Cell resize above viewport
29+
30+
When a cell above the viewport is resized (e.g., output grows), the viewport needs to be updated to maintain scroll position. This is handled by tracking scroll anchors.
31+
32+
![Cell Resize Above Viewport](./resources/notebook/cell-resize-above-viewport.drawio.svg)
33+
34+
## Cell Rendering
35+
36+
The notebook editor renders cells through a contribution system. Cell parts are organized into two categories via `CellPartsCollection`:
37+
38+
- **CellContentPart** - Non-floating elements rendered inside a cell synchronously to avoid flickering
39+
- `prepareRenderCell()` - Prepare model (no DOM operations)
40+
- `renderCell()` / `didRenderCell()` - Update DOM for the cell
41+
- `unrenderCell()` - Cleanup when cell leaves viewport
42+
- `updateInternalLayoutNow()` - Update layout per cell layout changes
43+
- `updateState()` - Update per cell state change
44+
- `updateForExecutionState()` - Update per execution state change
45+
46+
- **CellOverlayPart** - Floating elements rendered on top, may be deferred to next animation frame
47+
48+
Cell parts are located in `view/cellParts/` and contribute to different aspects:
49+
- **Editor** - The Monaco editor for code cells
50+
- **Outputs** - Rendered outputs from code execution
51+
- **Toolbar** - Cell toolbar with actions
52+
- **Status Bar** - Execution status, language info
53+
- **Decorations** - Fold regions, diagnostics, etc.
54+
- **Context Keys** - Cell-specific context key management
55+
- **Drag and Drop** - Cell reordering via `CellDragAndDropController`
56+
57+
## Focus Tracking
58+
59+
Focus in the notebook editor is complex because there are multiple focusable elements:
60+
61+
1. The notebook list itself (`NotebookCellList`)
62+
2. Individual cell containers
63+
3. Monaco editors within cells
64+
4. Output elements (webviews via `BackLayerWebView`)
65+
66+
The `NotebookEditorWidget` tracks focus state and provides APIs to manage focus across these components. Context keys like `NOTEBOOK_EDITOR_FOCUSED`, `NOTEBOOK_OUTPUT_FOCUSED`, and `NOTEBOOK_OUTPUT_INPUT_FOCUSED` are used to track focus state.
67+
68+
## Optimizations
69+
70+
### Output virtualization
71+
72+
Large outputs are virtualized similar to cells. Only visible portions of outputs are rendered.
73+
74+
### Cell DOM recycling
75+
76+
Cell DOM elements are pooled and recycled to reduce DOM operations. When scrolling, cells that move out of the viewport have their templates returned to the pool. Editor instances are managed via `NotebookCellEditorPool`.
77+
78+
### Webview reuse
79+
80+
Output webviews are reused across cells when possible to reduce the overhead of creating new webview contexts. The `BackLayerWebView` manages the webview lifecycle.
81+
82+
---
83+
84+
# Find in Notebook Outputs
85+
86+
The notebook find feature supports searching in both text models and rendered outputs. The find functionality is implemented via `FindModel` and `CellFindMatchModel` classes.
87+
88+
## Hybrid Find
89+
90+
For rendered outputs (HTML, images with alt text, etc.), the find uses a hybrid approach:
91+
92+
1. **Text model search** - Searches cell source code using standard text search via `FindMatch`
93+
2. **DOM search in webview** - Uses `window.find()` to search rendered output content via `CellWebviewFindMatch`
94+
95+
![Hybrid Find](./resources/notebook/hybrid-find.drawio.svg)
96+
97+
The hybrid find works by:
98+
99+
1. First finding matches in text models (cell inputs) - stored in `contentMatches`
100+
2. Then finding matches in rendered outputs via webview - stored in `webviewMatches`
101+
3. Mixing both match types into a unified result set via `CellFindMatchModel`
102+
4. Navigating between matches reveals the appropriate editor or output
103+
104+
### Implementation details
105+
106+
- Uses `window.find()` for DOM searching in webview
107+
- Uses `document.execCommand('hiliteColor')` to highlight matches
108+
- Serializes `document.getSelection()` to get match positions
109+
- Creates ranges for current match highlighting

0 commit comments

Comments
 (0)