Skip to content

Commit 70466bb

Browse files
author
colin-grant-work
authored
Implement missing API for [email protected] (#11083)
- LanguageStatusItem - TextDocumentChangeReason
1 parent 83e30af commit 70466bb

File tree

56 files changed

+1890
-315
lines changed

Some content is hidden

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

56 files changed

+1890
-315
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
- [plugin] Introduce `DebugSession#workspaceFolder` [#11090](https://github.com/eclipse-theia/theia/pull/11090) - Contributed on behalf of STMicroelectronics
1111
- [console] fixed issue in Debug console where console history was not being trimmed in accordance with the maximum commands limit [#10598](https://github.com/eclipse-theia/theia/pull/10598)
1212

13+
<a name="breaking_changes_1.26.0">[Breaking Changes:](#breaking_changes_1.26.0)</a>
14+
15+
- [callhierarchy] `paths.ts` and `glob.ts` moved to `core/src/common`; `language-selector.ts` moved to `editor/src/common`. Any imports will need to be updated.
16+
1317
## v1.25.0 - 4/28/2022
1418

1519
[1.25.0 Milestone](https://github.com/eclipse-theia/theia/milestone/35)

examples/api-tests/src/preferences.spec.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,21 @@ describe('Preferences', function () {
6666
}
6767

6868
async function deleteAllValues() {
69+
return setValueTo(undefined);
70+
}
71+
72+
/**
73+
* @param {any} value - A JSON value to write to the workspace preference file.
74+
*/
75+
async function setValueTo(value) {
6976
const reference = await modelService.createModelReference(uri);
7077
if (reference.object.dirty) {
7178
await reference.object.revert();
7279
}
7380
/** @type {import ('@theia/preferences/lib/browser/folder-preference-provider').FolderPreferenceProvider} */
7481
const provider = Array.from(folderPreferences['providers'].values()).find(candidate => candidate.getConfigUri().isEqual(uri));
7582
assert.isDefined(provider);
76-
await provider['doSetPreference']('', [], undefined);
83+
await provider['doSetPreference']('', [], value);
7784
reference.dispose();
7885
}
7986

@@ -92,7 +99,10 @@ describe('Preferences', function () {
9299
if (!fileExistsBeforehand) {
93100
await fileService.delete(uri, { fromUserGesture: false }).catch(() => { });
94101
} else {
95-
await fileService.write(uri, contentBeforehand);
102+
let content = '';
103+
try { content = JSON.parse(contentBeforehand); } catch { }
104+
// Use the preference service because its promise is guaranteed to resolve after the file change is complete.
105+
await setValueTo(content);
96106
}
97107
});
98108

examples/api-tests/src/typescript.spec.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ describe('TypeScript', function () {
4848
const contextKeyService = container.get(ContextKeyService);
4949
const commands = container.get(CommandRegistry);
5050
const openerService = container.get(OpenerService);
51+
/** @type {KeybindingRegistry} */
5152
const keybindings = container.get(KeybindingRegistry);
5253
/** @type {import('@theia/core/lib/browser/preferences/preference-service').PreferenceService} */
5354
const preferences = container.get(PreferenceService);
@@ -108,20 +109,21 @@ describe('TypeScript', function () {
108109
/**
109110
* @param {() => Promise<unknown> | unknown} condition
110111
* @param {number | undefined} [timeout]
112+
* @param {string | undefined} [message]
111113
* @returns {Promise<void>}
112114
*/
113-
function waitForAnimation(condition, timeout) {
114-
const success = new Promise(async (resolve, dispose) => {
115-
toTearDown.push({ dispose });
115+
function waitForAnimation(condition, timeout, message) {
116+
const success = new Promise(async (resolve, reject) => {
117+
toTearDown.push({ dispose: () => reject(message ?? 'Test terminated before resolution.') });
116118
do {
117119
await animationFrame();
118120
} while (!condition());
119121
resolve();
120122
});
121123
if (timeout !== undefined) {
122124
const timedOut = new Promise((_, fail) => {
123-
const toClear = setTimeout(() => fail(new Error('Wait for animation timed out.')), timeout);
124-
toTearDown.push({ dispose: () => (fail(new Error('Wait for animation timed out.')), clearTimeout(toClear)) });
125+
const toClear = setTimeout(() => fail(new Error(message ?? 'Wait for animation timed out.')), timeout);
126+
toTearDown.push({ dispose: () => (fail(new Error(message ?? 'Wait for animation timed out.')), clearTimeout(toClear)) });
125127
});
126128
return Promise.race([success, timedOut]);
127129
}
@@ -277,6 +279,7 @@ describe('TypeScript', function () {
277279
const from = 'an editor' + (preview ? ' preview' : '');
278280
it('within ' + from, async function () {
279281
const editor = await openEditor(demoFileUri, preview);
282+
editor.getControl().revealLine(24);
280283
// const demoInstance = new Demo|Class('demo');
281284
editor.getControl().setPosition({ lineNumber: 24, column: 30 });
282285
assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'DemoClass');
@@ -299,6 +302,7 @@ describe('TypeScript', function () {
299302
await editorManager.open(definitionFileUri, { mode: 'open' });
300303

301304
const editor = await openEditor(demoFileUri, preview);
305+
editor.getControl().revealLine(32);
302306
// const bar: Defined|Interface = { coolField: [] };
303307
editor.getControl().setPosition({ lineNumber: 32, column: 19 });
304308
assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'DefinedInterface');
@@ -319,6 +323,7 @@ describe('TypeScript', function () {
319323

320324
it(`from ${from} to an editor preview`, async function () {
321325
const editor = await openEditor(demoFileUri);
326+
editor.getControl().revealLine(32);
322327
// const bar: Defined|Interface = { coolField: [] };
323328
editor.getControl().setPosition({ lineNumber: 32, column: 19 });
324329
assert.equal(editor.getControl().getModel().getWordAtPosition(editor.getControl().getPosition()).word, 'DefinedInterface');
@@ -729,5 +734,4 @@ SPAN {
729734
assert.equal(getResultText(), expectedMessage);
730735
});
731736
}
732-
733737
});

examples/api-tests/src/undo-redo-selectAll.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ describe('Undo, Redo and Select All', function () {
6767
let originalValue = undefined;
6868
before(async () => {
6969
originalValue = preferenceService.inspect('files.autoSave').globalValue;
70-
await preferenceService.set('files.autoSave', false, PreferenceScope.User);
70+
await preferenceService.set('files.autoSave', 'off', PreferenceScope.User);
7171
shell.leftPanelHandler.collapse();
7272
});
7373

examples/playwright/src/theia-notification-indicator.ts

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,26 @@
1616

1717
import { TheiaStatusIndicator } from './theia-status-indicator';
1818

19-
const NOTIFICATION_ICON = 'codicon-bell';
2019
const NOTIFICATION_DOT_ICON = 'codicon-bell-dot';
21-
const NOTIFICATION_ICONS = [NOTIFICATION_ICON, NOTIFICATION_DOT_ICON];
2220

2321
export class TheiaNotificationIndicator extends TheiaStatusIndicator {
24-
25-
protected get title(): string {
26-
return 'Notification';
27-
}
28-
29-
override async isVisible(): Promise<boolean> {
30-
return super.isVisible(NOTIFICATION_ICONS, this.title);
31-
}
22+
id = 'theia-notification-center';
3223

3324
async hasNotifications(): Promise<boolean> {
34-
return super.isVisible(NOTIFICATION_DOT_ICON, this.title);
25+
const container = await this.getElementHandle();
26+
const bellWithDot = await container.$(`.${NOTIFICATION_DOT_ICON}`);
27+
return Boolean(bellWithDot?.isVisible());
3528
}
3629

3730
override async waitForVisible(expectNotifications = false): Promise<void> {
38-
await super.waitForVisibleByIcon(expectNotifications ? NOTIFICATION_DOT_ICON : NOTIFICATION_ICON);
31+
await super.waitForVisible();
32+
if (expectNotifications && !(await this.hasNotifications())) {
33+
throw new Error('No notifications when notifications expected.');
34+
}
3935
}
4036

4137
async toggleOverlay(): Promise<void> {
42-
const hasNotifications = await this.hasNotifications();
43-
const element = await this.getElementHandleByIcon(hasNotifications ? NOTIFICATION_DOT_ICON : NOTIFICATION_ICON, this.title);
38+
const element = await this.getElementHandle();
4439
if (element) {
4540
await element.click();
4641
}

examples/playwright/src/theia-problem-indicator.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,8 @@
1717
import { ElementHandle } from '@playwright/test';
1818
import { TheiaStatusIndicator } from './theia-status-indicator';
1919

20-
const PROBLEM_ICON = 'codicon-error';
21-
2220
export class TheiaProblemIndicator extends TheiaStatusIndicator {
23-
24-
override async isVisible(): Promise<boolean> {
25-
const handle = await super.getElementHandleByIcon(PROBLEM_ICON);
26-
return !!handle && handle.isVisible();
27-
}
21+
id = 'problem-marker-status';
2822

2923
async numberOfProblems(): Promise<number> {
3024
const spans = await this.getSpans();
@@ -37,8 +31,7 @@ export class TheiaProblemIndicator extends TheiaStatusIndicator {
3731
}
3832

3933
protected async getSpans(): Promise<ElementHandle[] | undefined> {
40-
const handle = await super.getElementHandleByIcon(PROBLEM_ICON);
34+
const handle = await this.getElementHandle();
4135
return handle?.$$('span');
4236
}
43-
4437
}

examples/playwright/src/theia-status-indicator.ts

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,60 +17,31 @@
1717
import { ElementHandle } from '@playwright/test';
1818
import { TheiaPageObject } from './theia-page-object';
1919

20-
export class TheiaStatusIndicator extends TheiaPageObject {
20+
export abstract class TheiaStatusIndicator extends TheiaPageObject {
21+
protected abstract id: string;
2122

22-
protected elementSpanSelector = '#theia-statusBar .element span';
23+
protected statusBarElementSelector = '#theia-statusBar div.element';
2324

24-
protected async getElementHandle(): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
25-
return this.page.$(this.elementSpanSelector);
25+
protected getSelectorForId(id: string): string {
26+
return `${this.statusBarElementSelector}#status-bar-${id}`;
2627
}
2728

28-
async waitForVisible(): Promise<void> {
29-
await this.page.waitForSelector(this.elementSpanSelector);
29+
async waitForVisible(waitForDetached = false): Promise<void> {
30+
await this.page.waitForSelector(this.getSelectorForId(this.id), waitForDetached ? { state: 'detached' } : {});
3031
}
3132

32-
protected getSelectorByTitle(title: string): string {
33-
return `.element[title="${title}"]`;
34-
}
35-
36-
async getElementHandleByTitle(title: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
37-
// Fetch element via title in case status elements exist without a dedicated Codicon icon
38-
return this.page.$(this.getSelectorByTitle(title));
39-
}
40-
41-
protected getSelectorByIcon(icon: string): string {
42-
return `${this.elementSpanSelector}.codicon.${icon}`;
43-
}
44-
45-
async getElementHandleByIcon(iconClass: string | string[], titleContain = ''): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
46-
const icons = Array.isArray(iconClass) ? iconClass : [iconClass];
47-
for (const icon of icons) {
48-
const span = await this.page.$(this.getSelectorByIcon(icon));
49-
if (span) {
50-
const parent = await span.$('..');
51-
if (titleContain === '') {
52-
return parent;
53-
} else {
54-
const parentTitle = await parent?.getAttribute('title');
55-
if (parentTitle?.includes(titleContain)) { return parent; }
56-
}
57-
}
33+
async getElementHandle(): Promise<ElementHandle<SVGElement | HTMLElement>> {
34+
const element = await this.page.$(this.getSelectorForId(this.id));
35+
if (element) {
36+
return element;
5837
}
59-
throw new Error('Cannot find indicator');
60-
}
61-
62-
async waitForVisibleByTitle(title: string, waitForDetached = false): Promise<void> {
63-
await this.page.waitForSelector(this.getSelectorByTitle(title), waitForDetached ? { state: 'detached' } : {});
64-
}
65-
66-
async waitForVisibleByIcon(icon: string, waitForDetached = false): Promise<void> {
67-
await this.page.waitForSelector(this.getSelectorByIcon(icon), waitForDetached ? { state: 'detached' } : {});
38+
throw new Error('Could not find status bar element with ID ' + this.id);
6839
}
6940

70-
async isVisible(icon: string | string[], titleContain = ''): Promise<boolean> {
41+
async isVisible(): Promise<boolean> {
7142
try {
72-
const element = await this.getElementHandleByIcon(icon, titleContain);
73-
return !!element && element.isVisible();
43+
const element = await this.getElementHandle();
44+
return element.isVisible();
7445
} catch (err) {
7546
return false;
7647
}

examples/playwright/src/theia-toggle-bottom-indicator.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616

1717
import { TheiaStatusIndicator } from './theia-status-indicator';
1818

19-
const TOGGLE_BOTTOM_ICON = 'codicon-window';
20-
2119
export class TheiaToggleBottomIndicator extends TheiaStatusIndicator {
22-
override async isVisible(): Promise<boolean> {
23-
return super.isVisible(TOGGLE_BOTTOM_ICON);
24-
}
20+
id = 'bottom-panel-toggle';
2521
}

packages/callhierarchy/src/browser/callhierarchy-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { CancellationToken } from '@theia/core';
2020
import URI from '@theia/core/lib/common/uri';
2121
import { ContributionProvider, Disposable, Emitter, Event } from '@theia/core/lib/common';
2222
import { CallHierarchyItem, CallHierarchyIncomingCall, CallHierarchyOutgoingCall } from './callhierarchy';
23-
import { LanguageSelector, score } from '../common/language-selector';
23+
import { LanguageSelector, score } from '@theia/editor/lib/common/language-selector';
2424

2525
export const CallHierarchyService = Symbol('CallHierarchyService');
2626

packages/core/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"@phosphor/signaling": "1",
1717
"@phosphor/virtualdom": "1",
1818
"@phosphor/widgets": "1",
19-
"@primer/octicons-react": "^9.0.0",
2019
"@theia/application-package": "1.25.0",
2120
"@types/body-parser": "^1.16.4",
2221
"@types/cookie": "^0.3.3",

0 commit comments

Comments
 (0)