@theia/core 1.73.0-next.31 → 1.73.0-next.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +19 -9
  2. package/lib/browser/catalog.json +12 -0
  3. package/lib/browser/markdown-rendering/markdown.d.ts +1 -1
  4. package/lib/browser/markdown-rendering/markdown.d.ts.map +1 -1
  5. package/lib/browser/markdown-rendering/markdown.js +1 -1
  6. package/lib/browser/markdown-rendering/markdown.js.map +1 -1
  7. package/lib/browser/menu/composite-menu-node.js +4 -4
  8. package/lib/browser/menu/composite-menu-node.js.map +1 -1
  9. package/lib/browser/preferences/preference-proxy.spec.js +7 -0
  10. package/lib/browser/preferences/preference-proxy.spec.js.map +1 -1
  11. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js +4 -4
  12. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.js.map +1 -1
  13. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js +2 -2
  14. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.js.map +1 -1
  15. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js +131 -0
  16. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.js.map +1 -1
  17. package/lib/browser/status-bar/status-bar.d.ts +2 -2
  18. package/lib/browser/status-bar/status-bar.d.ts.map +1 -1
  19. package/lib/browser/status-bar/status-bar.js.map +1 -1
  20. package/lib/browser/test/jsdom.d.ts +4 -0
  21. package/lib/browser/test/jsdom.d.ts.map +1 -1
  22. package/lib/browser/test/jsdom.js +18 -0
  23. package/lib/browser/test/jsdom.js.map +1 -1
  24. package/lib/browser/tree/tree-widget.js +2 -2
  25. package/lib/browser/tree/tree-widget.js.map +1 -1
  26. package/lib/common/preferences/injectable-preference-proxy.d.ts +3 -3
  27. package/lib/common/preferences/injectable-preference-proxy.d.ts.map +1 -1
  28. package/lib/common/preferences/injectable-preference-proxy.js +6 -1
  29. package/lib/common/preferences/injectable-preference-proxy.js.map +1 -1
  30. package/lib/common/preferences/preference-proxy.d.ts.map +1 -1
  31. package/lib/common/preferences/preference-proxy.js +6 -1
  32. package/lib/common/preferences/preference-proxy.js.map +1 -1
  33. package/lib/node/logger-cli-contribution.d.ts +6 -0
  34. package/lib/node/logger-cli-contribution.d.ts.map +1 -1
  35. package/lib/node/logger-cli-contribution.js +28 -5
  36. package/lib/node/logger-cli-contribution.js.map +1 -1
  37. package/lib/node/logger-cli-contribution.spec.js +54 -0
  38. package/lib/node/logger-cli-contribution.spec.js.map +1 -1
  39. package/package.json +26 -16
  40. package/src/browser/markdown-rendering/markdown.tsx +2 -2
  41. package/src/browser/menu/composite-menu-node.ts +4 -4
  42. package/src/browser/preferences/preference-proxy.spec.ts +8 -0
  43. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-menu-adapters.tsx +4 -4
  44. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar-registry.ts +2 -2
  45. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.spec.ts +159 -1
  46. package/src/browser/status-bar/status-bar.tsx +3 -3
  47. package/src/browser/test/jsdom.ts +18 -0
  48. package/src/browser/tree/tree-widget.tsx +2 -2
  49. package/src/common/preferences/injectable-preference-proxy.ts +10 -4
  50. package/src/common/preferences/preference-proxy.ts +10 -4
  51. package/src/node/logger-cli-contribution.spec.ts +65 -0
  52. package/src/node/logger-cli-contribution.ts +32 -5
@@ -239,7 +239,7 @@ export function createPreferenceProxy<T>(preferences: PreferenceService, promise
239
239
  return properties;
240
240
  };
241
241
 
242
- const set: (target: any, prop: string, value: any, receiver: any) => boolean = (_, property: string | symbol | number, value: any) => {
242
+ const set: (target: any, prop: string | symbol, value: any, receiver: any) => boolean = (_, property: string | symbol | number, value: any) => {
243
243
  if (typeof property !== 'string') {
244
244
  throw new Error(`unexpected property: ${String(property)}`);
245
245
  }
@@ -270,7 +270,13 @@ export function createPreferenceProxy<T>(preferences: PreferenceService, promise
270
270
  return false;
271
271
  };
272
272
 
273
- const get: (target: any, prop: string) => any = (_, property: string | symbol | number) => {
273
+ const get: (target: any, prop: string | symbol) => any = (_, property: string | symbol | number) => {
274
+ // React 19 dev mode calls Object.prototype.toString when handling prop diffs, which
275
+ // probes Symbol.toStringTag. Throwing should be avoided in this case, it crashes the React DOM.
276
+ if (property === Symbol.toStringTag) {
277
+ return undefined;
278
+ }
279
+
274
280
  if (typeof property !== 'string') {
275
281
  throw new Error(`unexpected property: ${String(property)}`);
276
282
  }
@@ -347,8 +353,8 @@ export function createPreferenceProxy<T>(preferences: PreferenceService, promise
347
353
  return new Proxy({}, {
348
354
  get,
349
355
  ownKeys,
350
- getOwnPropertyDescriptor: (_, property: string) => {
351
- if (ownKeys().indexOf(property) !== -1) {
356
+ getOwnPropertyDescriptor: (_, property: string | symbol) => {
357
+ if (typeof property === 'string' && ownKeys().indexOf(property) !== -1) {
352
358
  return {
353
359
  enumerable: true,
354
360
  configurable: true
@@ -257,4 +257,69 @@ describe('log-level-cli-contribution', () => {
257
257
  world: LogLevel.FATAL,
258
258
  });
259
259
  });
260
+
261
+ describe('Wildcard Matching', () => {
262
+
263
+ async function setupLogLevels(levels: { [key: string]: string }): Promise<void> {
264
+ const file = track.openSync();
265
+ fs.writeFileSync(file.fd, JSON.stringify({
266
+ defaultLevel: 'info',
267
+ levels
268
+ }));
269
+ fs.fsyncSync(file.fd);
270
+ fs.closeSync(file.fd);
271
+
272
+ const args: yargs.Arguments = await yargs.parse(['--log-config', file.path]);
273
+ await cli.setArguments(args);
274
+ }
275
+
276
+ it('should respect exact matches without wildcards', async () => {
277
+ await setupLogLevels({
278
+ 'unrelated:Service': 'debug'
279
+ });
280
+ expect(cli.logLevelFor('unrelated:Service')).to.equal(LogLevel.DEBUG);
281
+ expect(cli.logLevelFor('something-else')).to.equal(LogLevel.INFO);
282
+ });
283
+
284
+ it('should match prefix wildcards', async () => {
285
+ await setupLogLevels({
286
+ 'ai-core*': 'error'
287
+ });
288
+ expect(cli.logLevelFor('ai-core:SomeOtherService')).to.equal(LogLevel.ERROR);
289
+ });
290
+
291
+ it('should match suffix wildcards', async () => {
292
+ await setupLogLevels({
293
+ '*TokenUsageFrontendServiceImpl': 'warn'
294
+ });
295
+ expect(cli.logLevelFor('my-package:MyTokenUsageFrontendServiceImpl')).to.equal(LogLevel.WARN);
296
+ });
297
+
298
+ it('should match middle wildcards', async () => {
299
+ await setupLogLevels({
300
+ '*ai*:*': 'warn'
301
+ });
302
+ expect(cli.logLevelFor('foo-ai-bar:SomeService')).to.equal(LogLevel.WARN);
303
+ });
304
+
305
+ it('should enforce perfect match first, then last wildcard wins', async () => {
306
+ await setupLogLevels({
307
+ 'ai-core*': 'error',
308
+ '*ai*:*': 'warn',
309
+ 'ai-core:SpecificService': 'debug'
310
+ });
311
+
312
+ expect(cli.logLevelFor('ai-core:SpecificService')).to.equal(LogLevel.DEBUG);
313
+
314
+ expect(cli.logLevelFor('ai-core:OtherService')).to.equal(LogLevel.WARN);
315
+ });
316
+
317
+ it('should properly escape regex specifics like periods', async () => {
318
+ await setupLogLevels({
319
+ '.*': 'error'
320
+ });
321
+ expect(cli.logLevelFor('anything-else')).to.equal(LogLevel.INFO);
322
+ expect(cli.logLevelFor('.*')).to.equal(LogLevel.ERROR);
323
+ });
324
+ });
260
325
  });
@@ -23,6 +23,7 @@ import { AsyncSubscription, subscribe } from '@parcel/watcher';
23
23
  import { Event, Emitter } from '../common/event';
24
24
  import * as path from 'path';
25
25
  import { Disposable, DisposableCollection } from '../common';
26
+ import { escapeRegExpCharacters } from '../common/strings';
26
27
 
27
28
  /** Maps logger names to log levels. */
28
29
  export interface LogLevels {
@@ -38,6 +39,7 @@ export interface LogLevels {
38
39
  export class LogLevelCliContribution implements CliContribution, Disposable {
39
40
 
40
41
  protected _logLevels: LogLevels = {};
42
+ protected wildcardRegexCache = new Map<string, RegExp>();
41
43
  protected asyncSubscriptions: AsyncSubscription[] = [];
42
44
  protected toDispose = new DisposableCollection();
43
45
 
@@ -190,6 +192,7 @@ export class LogLevelCliContribution implements CliContribution, Disposable {
190
192
 
191
193
  this._defaultLogLevel = newDefaultLogLevel;
192
194
  this._logLevels = newLogLevels;
195
+ this.wildcardRegexCache.clear();
193
196
 
194
197
  console.log(`Successfully read new log config from ${filename}.`);
195
198
  } catch (e) {
@@ -202,13 +205,23 @@ export class LogLevelCliContribution implements CliContribution, Disposable {
202
205
  }
203
206
 
204
207
  logLevelFor(loggerName: string): LogLevel {
205
- const level = this._logLevels[loggerName];
208
+ if (loggerName in this._logLevels) {
209
+ return this._logLevels[loggerName];
210
+ }
211
+
212
+ const keys = Object.keys(this._logLevels);
213
+ for (let i = keys.length - 1; i >= 0; i--) {
214
+ const pattern = keys[i];
206
215
 
207
- if (level !== undefined) {
208
- return level;
209
- } else {
210
- return this.defaultLogLevel;
216
+ if (pattern.includes('*')) {
217
+ const regex = this.getWildcardRegex(pattern);
218
+ if (regex.test(loggerName)) {
219
+ return this._logLevels[pattern];
220
+ }
221
+ }
211
222
  }
223
+
224
+ return this.defaultLogLevel;
212
225
  }
213
226
 
214
227
  /**
@@ -223,4 +236,18 @@ export class LogLevelCliContribution implements CliContribution, Disposable {
223
236
 
224
237
  return level;
225
238
  }
239
+
240
+ /**
241
+ * Converts a wildcard string into a strict regular expression and caches it.
242
+ * Example: "ai-core*" -> /^ai-core.*$/
243
+ */
244
+ protected getWildcardRegex(pattern: string): RegExp {
245
+ let regex = this.wildcardRegexCache.get(pattern);
246
+ if (!regex) {
247
+ const escapedPattern = pattern.split('*').map(escapeRegExpCharacters).join('.*');
248
+ regex = new RegExp(`^${escapedPattern}$`);
249
+ this.wildcardRegexCache.set(pattern, regex);
250
+ }
251
+ return regex;
252
+ }
226
253
  }