Skip to content

Commit

Permalink
Merge pull request #159321 from microsoft/aiday/issue159271
Browse files Browse the repository at this point in the history
Sticky Scroll : Take into account child scope starting on the same line as the parent scope
  • Loading branch information
Aiday Marlen Kyzy authored Aug 29, 2022
2 parents ec5b41d + 99de729 commit 3cba0ec
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 8 deletions.
16 changes: 12 additions & 4 deletions src/vs/editor/contrib/stickyScroll/browser/stickyScrollProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class StickyLineCandidateProvider extends Disposable {
if (token.isCancellationRequested) {
return;
}
this._outlineModel = StickyOutlineElement.fromOutlineModel(outlineModel);
this._outlineModel = StickyOutlineElement.fromOutlineModel(outlineModel, -1);
this._modelVersionId = modelVersionId;
}
}
Expand Down Expand Up @@ -158,12 +158,20 @@ export class StickyLineCandidateProvider extends Disposable {
}

class StickyOutlineElement {
public static fromOutlineModel(outlineModel: OutlineModel | OutlineElement | OutlineGroup): StickyOutlineElement {
public static fromOutlineModel(outlineModel: OutlineModel | OutlineElement | OutlineGroup, previousStartLine: number): StickyOutlineElement {

const children: StickyOutlineElement[] = [];
for (const child of outlineModel.children.values()) {
if (child instanceof OutlineElement && child.symbol.selectionRange.startLineNumber !== child.symbol.range.endLineNumber || child instanceof OutlineGroup || child instanceof OutlineModel) {
children.push(StickyOutlineElement.fromOutlineModel(child));
if (child instanceof OutlineGroup || child instanceof OutlineModel) {
children.push(StickyOutlineElement.fromOutlineModel(child, previousStartLine));
} else if (child instanceof OutlineElement && child.symbol.selectionRange.startLineNumber !== child.symbol.range.endLineNumber) {
if (child.symbol.selectionRange.startLineNumber !== previousStartLine) {
children.push(StickyOutlineElement.fromOutlineModel(child, child.symbol.selectionRange.startLineNumber));
} else {
for (const subchild of child.children.values()) {
children.push(StickyOutlineElement.fromOutlineModel(subchild, child.symbol.selectionRange.startLineNumber));
}
}
}
}
children.sort((child1, child2) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeatu
import { DocumentSymbol, SymbolKind } from 'vs/editor/common/languages';
import { StickyLineCandidate, StickyLineCandidateProvider } from 'vs/editor/contrib/stickyScroll/browser/stickyScrollProvider';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';

suite('Sticky Scroll Tests', () => {

const serviceCollection = new ServiceCollection(
[ILanguageFeaturesService, new LanguageFeaturesService()]
[ILanguageFeaturesService, new LanguageFeaturesService()],
[ILogService, new NullLogService()]
);

const text = [
Expand Down Expand Up @@ -121,10 +123,10 @@ suite('Sticky Scroll Tests', () => {
await withAsyncTestCodeEditor(model, { serviceCollection }, async (editor, _viewModel, instantiationService) => {

const stickyScrollController: StickyScrollController = editor.registerAndInstantiateContribution(StickyScrollController.ID, StickyScrollController);
await stickyScrollController.stickyScrollCandidateProvider.update();
const lineHeight: number = editor.getOption(EditorOption.lineHeight);
const languageService: ILanguageFeaturesService = instantiationService.get(ILanguageFeaturesService);
languageService.documentSymbolProvider.register('*', documentSymbolProviderForTestModel());
await stickyScrollController.stickyScrollCandidateProvider.update();
let state;

editor.setScrollTop(1);
Expand Down Expand Up @@ -163,12 +165,11 @@ suite('Sticky Scroll Tests', () => {
await withAsyncTestCodeEditor(model, { serviceCollection }, async (editor, viewModel, instantiationService) => {

const stickyScrollController: StickyScrollController = editor.registerAndInstantiateContribution(StickyScrollController.ID, StickyScrollController);
await stickyScrollController.stickyScrollCandidateProvider.update();
const lineHeight = editor.getOption(EditorOption.lineHeight);

const languageService = instantiationService.get(ILanguageFeaturesService);
languageService.documentSymbolProvider.register('*', documentSymbolProviderForTestModel());

await stickyScrollController.stickyScrollCandidateProvider.update();
editor.setHiddenAreas([{ startLineNumber: 2, endLineNumber: 2, startColumn: 1, endColumn: 1 }, { startLineNumber: 10, endLineNumber: 11, startColumn: 1, endColumn: 1 }]);
let state;

Expand Down Expand Up @@ -197,4 +198,90 @@ suite('Sticky Scroll Tests', () => {
model.dispose();
});
});

const textWithScopesWithSameStartingLines = [
'class TestClass { foo() {',
'function bar(){',
'',
'}}',
'}',
''
].join('\n');

function documentSymbolProviderForSecondTestModel() {
return {
provideDocumentSymbols() {
return [
{
name: 'TestClass',
detail: 'TestClass',
kind: SymbolKind.Class,
tags: [],
range: { startLineNumber: 1, endLineNumber: 5, startColumn: 1, endColumn: 1 },
selectionRange: { startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: 1 },
children: [
{
name: 'foo',
detail: 'foo',
kind: SymbolKind.Function,
tags: [],
range: { startLineNumber: 1, endLineNumber: 4, startColumn: 1, endColumn: 1 },
selectionRange: { startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: 1 },
children: [
{
name: 'bar',
detail: 'bar',
kind: SymbolKind.Function,
tags: [],
range: { startLineNumber: 2, endLineNumber: 4, startColumn: 1, endColumn: 1 },
selectionRange: { startLineNumber: 2, endLineNumber: 2, startColumn: 1, endColumn: 1 },
children: []
} as DocumentSymbol
]
} as DocumentSymbol,
]
} as DocumentSymbol
];
}
};
}

test('issue #159271 : render the correct widget state when the child scope starts on the same line as the parent scope', async () => {

const model = createTextModel(textWithScopesWithSameStartingLines);
await withAsyncTestCodeEditor(model, { serviceCollection }, async (editor, _viewModel, instantiationService) => {

const stickyScrollController: StickyScrollController = editor.registerAndInstantiateContribution(StickyScrollController.ID, StickyScrollController);
const lineHeight = editor.getOption(EditorOption.lineHeight);

const languageService = instantiationService.get(ILanguageFeaturesService);
languageService.documentSymbolProvider.register('*', documentSymbolProviderForSecondTestModel());
await stickyScrollController.stickyScrollCandidateProvider.update();
let state;

editor.setScrollTop(1);
state = stickyScrollController.getScrollWidgetState();
assert.deepStrictEqual(state.lineNumbers, [1, 2]);

editor.setScrollTop(lineHeight + 1);
state = stickyScrollController.getScrollWidgetState();
assert.deepStrictEqual(state.lineNumbers, [1, 2]);

editor.setScrollTop(2 * lineHeight + 1);
state = stickyScrollController.getScrollWidgetState();
assert.deepStrictEqual(state.lineNumbers, [1]);

editor.setScrollTop(3 * lineHeight + 1);
state = stickyScrollController.getScrollWidgetState();
assert.deepStrictEqual(state.lineNumbers, [1]);

editor.setScrollTop(4 * lineHeight + 1);
state = stickyScrollController.getScrollWidgetState();
assert.deepStrictEqual(state.lineNumbers, []);

stickyScrollController.dispose();
stickyScrollController.stickyScrollCandidateProvider.dispose();
model.dispose();
});
});
});

0 comments on commit 3cba0ec

Please sign in to comment.