Change:
use autofolding of imports . use a type that is not imported in a TS file use quick fix to add the import the editor scrolls to an incorrect position. I think this is a recent regression, because I've been using both import folding and quick fix for imports since quite a while... maybe starting with the last stable. https://user- Version: 1.72.0-insider Commit: Date: 2022-09-21T05:40:07.654Z Electron: 19.0.17 Chromium: 102.0.5005.167 16.14.2 V8: 10.2.154.15-electron.0 OS: Darwin arm64 21.6.0 Sandboxed: Yes
Un-assigning myself as I don't think this cause by something the JS/TS extension itself is doing
who owns the quick fix UI now?
I own the UI. However it looks like scrolling here happen when the edit from the quick fix is applied. That's why I unassigned myself
It also unfolds if you do "Organize Imports", so seems like any action related with imports unfolds even though setting is
The root cause appears to be the folding ranges change and end up calling . That one does not attempt to maintain the viewport stable in any way.
this issue still exists:

Discussion:
this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewCompositionEndEvent()); } <del> private _onConfigurationChanged(eventsCollector: ViewModelEventsCollector, e: ConfigurationChangedEvent): void { // We might need to restore the current centered view range, so save it (if available) let previousViewportStartModelPosition: Position | null = null; if (this._viewportStart.isValid) { </del> <ins> private _captureStableViewport(): StableViewport { // We might need to restore the current start view range, so save it (if available) // But only if the scroll position is not at the top of the file if (this._viewportStart.isValid && this.viewLayout.getCurrentScrollTop() > 0) { </ins> const previousViewportStartViewPosition = new Position(this._viewportStart.viewLineNumber, this.getLineMinColumn(this._viewportStart.viewLineNumber)); <del> previousViewportStartModelPosition = this.coordinatesConverter.convertViewPositionToModelPosition(previousViewportStartViewPosition); </del> <ins> const previousViewportStartModelPosition = this.coordinatesConverter.convertViewPositionToModelPosition(previousViewportStartViewPosition); return new StableViewport(previousViewportStartModelPosition, this._viewportStart.startLineDelta); </ins> } <del> let restorePreviousViewportStart = false; </del> <ins> return new StableViewport(null, 0); } private _onConfigurationChanged(eventsCollector: ViewModelEventsCollector, e: ConfigurationChangedEvent): void { const stableViewport = this._captureStableViewport(); </ins> const options = this._configuration.options; const fontInfo = options.get(EditorOption.fontInfo); const wrappingStrategy = options.get(EditorOption.wrappingStrategy);

this._decorations.onLineMappingChanged(); this.viewLayout.onFlushed(this.getLineCount()); <del> if (this.viewLayout.getCurrentScrollTop() !== 0) { // Never change the scroll position from 0 to something else... restorePreviousViewportStart = true; } </del> this._updateConfigurationViewLineCount.schedule(); }

eventsCollector.emitViewEvent(new viewEvents.ViewConfigurationChangedEvent(e)); this.viewLayout.onConfigurationChanged(e); <del> if (restorePreviousViewportStart && previousViewportStartModelPosition) { const viewPosition = this.coordinatesConverter.convertModelPositionToViewPosition(previousViewportStartModelPosition); const viewPositionTop = this.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber); this.viewLayout.setScrollPosition({ scrollTop: viewPositionTop + this._viewportStart.startLineDelta }, ScrollType.Immediate); } </del> <ins> stableViewport.recoverViewportStart(this.coordinatesConverter, this.viewLayout); </ins> if (CursorConfiguration.shouldRecreate(e)) { this.cursorConfig = new CursorConfiguration(this.model.getLanguageId(), this.model.getOptions(), this._configuration, this.languageConfigurationService);

this.previousHiddenAreas = mergedRanges; <ins> const stableViewport = this._captureStableViewport(); </ins> let lineMappingChanged = false; try { const eventsCollector = this._eventDispatcher.beginEmitViewEvents();

this.viewLayout.onFlushed(this.getLineCount()); this.viewLayout.onHeightMaybeChanged(); } <ins> stableViewport.recoverViewportStart(this.coordinatesConverter, this.viewLayout); </ins> } finally { this._eventDispatcher.endEmitViewEvents(); }

} return true; } <ins> /** * Maintain a stable viewport by trying to keep the first line in the viewport constant. */ class StableViewport { constructor( public readonly viewportStartModelPosition: Position | null, public readonly startLineDelta: number ) { } public recoverViewportStart(coordinatesConverter: ICoordinatesConverter, viewLayout: ViewLayout): void { if (!this.viewportStartModelPosition) { return; } const viewPosition = coordinatesConverter.convertModelPositionToViewPosition(this.viewportStartModelPosition); const viewPositionTop = viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber); viewLayout.setScrollPosition({ scrollTop: viewPositionTop + this.startLineDelta }, ScrollType.Immediate); } } </ins>