Skip to content

Commit

Permalink
refactor: add @opensumi/ide-utils module (#784)
Browse files Browse the repository at this point in the history
* refactor: add @opensumi/ide-utils module

* fix: module and function ref path

* test: move utils test to utils module

* chore: upgrade to 2.16.6 version

* refactor: use common OperatingSystem define on platform and os file

* chore: remove useless utils

* test: fix unit test

* test: use ResourceLoader on jsdom to make platform correctly

* chore: make @opensumi/ide-utils to be public package

* chore: merge cancelToken defined

* chore: fix function ref

* chore: add userAgent environment in jsdom

* chore: add prettierPath config

* chore: update jest.config.js

* test: add more arrays unit test

* chore: use v8 coverageProvider

* chore: use babel provider

* chore: add codecov.yml

* chore: update utils version

Co-authored-by: 野声 <[email protected]>
  • Loading branch information
erha19 and bytemain authored Apr 27, 2022
1 parent 568c393 commit 3340fa8
Show file tree
Hide file tree
Showing 370 changed files with 1,593 additions and 6,126 deletions.
8 changes: 8 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
target: auto
# allow coverage to drop by this amount and still post success
threshold: 0.5%
if_ci_failed: error
8 changes: 8 additions & 0 deletions configs/ts/references/tsconfig.utils.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"rootDir": "../../../packages/utils/src",
"outDir": "../../../packages/utils/lib"
},
"include": ["../../../packages/utils/src"]
}
3 changes: 3 additions & 0 deletions configs/ts/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"references": [
{
"path": "./references/tsconfig.utils.json"
},
{
"path": "./references/tsconfig.core-common.json"
},
Expand Down
2 changes: 2 additions & 0 deletions configs/ts/tsconfig.resolve.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"compilerOptions": {
"baseUrl": "..",
"paths": {
"@opensumi/ide-utils": ["../packages/utils/src/index.ts"],
"@opensumi/ide-utils/lib/*": ["../packages/utils/src/*"],
"@opensumi/ide-addons": ["../packages/addons/src/index.ts"],
"@opensumi/ide-addons/lib/*": ["../packages/addons/src/*"],
"@opensumi/ide-comments": ["../packages/comments/src/index.ts"],
Expand Down
14 changes: 4 additions & 10 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,15 @@ const baseConfig = {
'/packages/quick-open/entry',
// 终端渲染测试暂时不跟随单元测试
'/packages/terminal-next/__tests__/browser/render.test.ts',
// components utils 均引用自 @opensumi/ide-core-common 模块,无须重复测试
// 后续统一至 @opensumi/ide-utils 模块
'/packages/components/src/utils',
],
modulePathIgnorePatterns: ['<rootDir>/dist/'],
coveragePathIgnorePatterns: [
'/dist/',
'/node_modules/',
'/__test__/',
'/mocks/',
'/tools/template/',
'/tools/workspace/',
'/packages/status-bar/entry',
'/packages/startup/entry',
'/packages/quick-open/entry',
// components 下的 utils 均引用自 @opensumi/ide-core-common 模块,无须重复测试
// 后续统一至 @opensumi/ide-utils 模块
'/packages/components/src/utils',
],
coverageThreshold: {
global: {
Expand All @@ -78,7 +69,7 @@ module.exports = {
// 有个 webview 的 case 应该放在 electron 下测,也会被第一条规则匹配到
// - packages/webview/__tests__/webview/webview.channel.test.ts
'**/packages/*/__test?(s)__/!(browser)/**/?(*.)+(spec|test).[jt]s?(x)',
'**/packages/{core-common,core-electron-main,core-node,electron-basic}/__tests__/**/?(*.)+(spec|test).[jt]s?(x)',
'**/packages/{core-common,core-electron-main,core-node,electron-basic,utils}/__tests__/**/?(*.)+(spec|test).[jt]s?(x)',
// exclude 的要放最后
'!**/packages/{components,core-browser}/__tests__/**',
],
Expand All @@ -93,6 +84,9 @@ module.exports = {
</html>`,
runScripts: 'dangerously',
url: 'http://localhost/?id=1',
userAgent: `Mozilla/5.0 (${
process.platform === 'darwin' ? 'Macintosh' : process.platform === 'win32' ? 'Windows' : 'Linux'
}) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/v16.7.0`,
},
setupFiles: ['./jest.setup.jsdom.js'],
testMatch: [
Expand Down
12 changes: 11 additions & 1 deletion jest.setup.node.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
const { JSDOM } = require('jsdom');
const { JSDOM, ResourceLoader } = require('jsdom');

const resourceLoader = new ResourceLoader({
strictSSL: false,
userAgent: `Mozilla/5.0 (${
process.platform === 'darwin' ? 'Macintosh' : process.platform === 'win32' ? 'Windows' : 'Linux'
}) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/v16.7.0`,
});

const jsdom = new JSDOM('<div id="main"></div>', {
// https://github.com/jsdom/jsdom#basic-options
// 禁用掉 resources: usable, 采用 jsdom 默认策略不加载 subresources
// 避免测试用例加载 external subresource, 如 iconfont 的 css 挂掉
// resources: 'usable',
runScripts: 'dangerously',
url: 'http://localhost/?id=1',
// 保障 `platform.ts` 中 isLinux 等平台信息判断准确性
resources: resourceLoader,
});
global.document = jsdom.window.document;
let text = '';
Expand Down
7 changes: 4 additions & 3 deletions packages/addons/src/browser/file-drop.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Injectable, Autowired } from '@opensumi/di';
import { Path } from '@opensumi/ide-components/lib/utils/path';
import { Uri, formatLocalize } from '@opensumi/ide-core-browser/lib';
import { formatLocalize } from '@opensumi/ide-core-browser';
import { IStatusBarService, StatusBarAlignment, StatusBarEntryAccessor } from '@opensumi/ide-core-browser/lib/services';
import { WithEventBus } from '@opensumi/ide-core-common/lib';
import { WithEventBus, Uri, path } from '@opensumi/ide-core-common';
import { FileTreeDropEvent } from '@opensumi/ide-core-common/lib/types/dnd';
import { IFileServiceClient } from '@opensumi/ide-file-service/lib/common';

const { Path } = path;

import {
IFileDropFrontendService,
IFileDropBackendService,
Expand Down
6 changes: 4 additions & 2 deletions packages/comments/src/browser/comments.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import {
IDisposable,
positionToRange,
Deferred,
path,
LRUCache,
} from '@opensumi/ide-core-browser';
import { LRUCache } from '@opensumi/ide-core-common/lib/map';
import { dirname } from '@opensumi/ide-core-common/lib/path';
import { IEditor } from '@opensumi/ide-editor';
import {
IEditorDecorationCollectionService,
Expand All @@ -46,6 +46,8 @@ import {
import { CommentsPanel } from './comments-panel.view';
import { CommentsThread } from './comments-thread';

const { dirname } = path;

@Injectable()
export class CommentsService extends Disposable implements ICommentsService {
@Autowired(INJECTOR_TOKEN)
Expand Down
1 change: 1 addition & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"dependencies": {
"@ant-design/icons": "^4.6.4",
"@types/react-window": "^1.8.5",
"@opensumi/ide-utils": "2.17.0",
"fuzzy": "^0.1.3",
"lodash": "^4.17.15",
"raf": "^3.4.1",
Expand Down
56 changes: 12 additions & 44 deletions packages/components/src/recycle-tree/RecycleTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@ import fuzzy from 'fuzzy';
import React from 'react';
import { FixedSizeList, VariableSizeList, shouldComponentUpdate, ListProps } from 'react-window';

import {
DisposableCollection,
Emitter,
Event,
Disposable,
CancellationTokenSource,
CancellationToken,
Throttler,
} from '@opensumi/ide-utils';

import { ScrollbarsVirtualList } from '../scrollbars';
import { DisposableCollection, Emitter, Event, Disposable, CancellationTokenSource, CancellationToken } from '../utils';

import { RenamePromptHandle, PromptHandle } from './prompt';
import { NewPromptHandle } from './prompt/NewPromptHandle';
Expand Down Expand Up @@ -286,8 +295,7 @@ export class RecycleTree extends React.Component<IRecycleTreeProps> {

private willUpdateTasks = 0;

private updateTimer;
private updateTime = 0;
private queueUpdateThrottler: Throttler = new Throttler();

// 批量更新Tree节点
private doBatchUpdate = (() => {
Expand Down Expand Up @@ -376,52 +384,12 @@ export class RecycleTree extends React.Component<IRecycleTreeProps> {
};
})();

// FIXME: 待 @opensumi/ide-utils 合入后可合并逻辑至 Throttler.queue
private batchUpdate = () => {
this.willUpdateTasks++;
this.queueUpdatePromise = this.queueUpdate(this.doBatchUpdate);
this.queueUpdatePromise = this.queueUpdateThrottler.queue(this.doBatchUpdate);
return this.queueUpdatePromise;
};

private queueUpdate(promiseFactory: () => Promise<void>) {
if (this.activePromise) {
this.queuedPromiseFactory = promiseFactory;

if (!this.queuedPromise) {
const onComplete = () => {
this.queuedPromise = null;

const result = this.queueUpdate(this.queuedPromiseFactory!);
this.queuedPromiseFactory = null;

return result;
};

this.queuedPromise = new Promise((c) => {
this.activePromise!.then(onComplete, onComplete).then(c);
});
}
return new Promise((c, e) => {
this.queuedPromise!.then(c, e);
});
}

this.activePromise = promiseFactory();

return new Promise((c, e) => {
this.activePromise!.then(
(result: any) => {
this.activePromise = null;
c(result);
},
(err: any) => {
this.activePromise = null;
e(err);
},
);
});
}

private getNewPromptInsertIndex(startIndex: number, parent: CompositeTreeNode) {
const { root } = this.props.model;
let insertIndex: number = startIndex + 1;
Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/recycle-tree/basic/tree-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DisposableCollection, Emitter } from '../../utils';
import { DisposableCollection, Emitter } from '@opensumi/ide-utils';

import { TreeModel, Tree, Decoration, DecorationsManager } from '../tree';
import { TreeNodeEvent } from '../types';

Expand Down
5 changes: 3 additions & 2 deletions packages/components/src/recycle-tree/prompt/PromptHandle.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DisposableCollection, Emitter, Event, IAsyncResult } from '@opensumi/ide-utils';

import { bindInputElement, ProxiedInputProp } from '../../input';
import { DisposableCollection, Emitter, Event, IAsyncResult } from '../../utils';

const delay = (ms) => new Promise((res) => setTimeout(res, ms));

Expand Down Expand Up @@ -171,7 +172,7 @@ export abstract class PromptHandle {
return;
}
// 获取最顶层的父级焦点容器
let element = this.focusPrevActiveElement();
const element = this.focusPrevActiveElement();
this._destroyed = true;
this.$.removeEventListener('click', this.handleClick);
this.$.removeEventListener('keyup', this.handleKeyup);
Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/recycle-tree/tree/Tree.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Emitter, DisposableCollection } from '../../utils';
import { Emitter, DisposableCollection } from '@opensumi/ide-utils';

import { ITreeNodeOrCompositeTreeNode, ITree, ICompositeTreeNode } from '../types';

import { TreeNode, CompositeTreeNode } from './TreeNode';
Expand Down
60 changes: 13 additions & 47 deletions packages/components/src/recycle-tree/tree/TreeNode.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
/* eslint-disable @typescript-eslint/prefer-for-of */
import { Event, Emitter, DisposableCollection, Path, CancellationToken, CancellationTokenSource } from '../../utils';
import {
Event,
Emitter,
DisposableCollection,
path,
CancellationToken,
CancellationTokenSource,
Throttler,
} from '@opensumi/ide-utils';

import {
IWatcherCallback,
IWatchTerminator,
Expand All @@ -18,6 +27,7 @@ import {
IAccessibilityInformation,
} from '../types';

const { Path } = path;
/**
* 裁剪数组
*
Expand Down Expand Up @@ -349,9 +359,7 @@ export class CompositeTreeNode extends TreeNode implements ICompositeTreeNode {
private _branchSize: number;
private _flattenedBranch: number[] | null;

private activeRefreshPromise: Promise<any> | null;
private queuedRefreshPromise: Promise<any> | null;
private queuedRefreshPromiseFactory: ((token?: CancellationToken) => Promise<any>) | null;
private refreshThrottler: Throttler = new Throttler();

private _lock = false;

Expand Down Expand Up @@ -1414,54 +1422,12 @@ export class CompositeTreeNode extends TreeNode implements ICompositeTreeNode {
} else {
token = state.refreshCancelToken.token;
}
await this.queue<void>(this.doRefresh.bind(this), token);
await this.refreshThrottler.queue(async () => this.doRefresh(token));
TreeNode.setGlobalTreeState(this.path, {
isRefreshing: false,
});
}

private async queue<T>(promiseFactory: (token?: CancellationToken) => Promise<T>, token?: CancellationToken) {
if (this.activeRefreshPromise) {
this.queuedRefreshPromiseFactory = promiseFactory;

if (!this.queuedRefreshPromise) {
const onComplete = () => {
if (token?.isCancellationRequested) {
return async () => {};
}
this.queuedRefreshPromise = null;
const result = this.queue(() => this.queuedRefreshPromiseFactory!(token));
this.queuedRefreshPromiseFactory = null;

return result;
};

this.queuedRefreshPromise = new Promise((resolve) => {
this.activeRefreshPromise?.then(onComplete, onComplete).then(resolve);
});
}

return new Promise<T>((c, e) => {
this.queuedRefreshPromise?.then(c, e);
});
}

this.activeRefreshPromise = promiseFactory(token);

return new Promise<T>((c, e) => {
this.activeRefreshPromise?.then(
(result: any) => {
this.activeRefreshPromise = null;
c(result);
},
(err: any) => {
this.activeRefreshPromise = null;
e(err);
},
);
});
}

private async doRefresh(token?: CancellationToken) {
const paths = this.getAllExpandedNodePath();
await this.refreshTreeNodeByPaths(paths, true, token);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DisposableCollection } from '../../../utils';
import { DisposableCollection } from '@opensumi/ide-utils';

import { ITreeNodeOrCompositeTreeNode } from '../../types';

import { Decoration, TargetMatchMode, IDecorationEventData } from './Decoration';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IDisposable, Disposable, Emitter } from '../../../utils';
import { IDisposable, Disposable, Emitter } from '@opensumi/ide-utils';

import { ITreeNode, ICompositeTreeNode } from '../../types';
import { TreeNode } from '../TreeNode';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IDisposable, DisposableCollection } from '../../../utils';
import { IDisposable, DisposableCollection } from '@opensumi/ide-utils';

import { TreeNodeEvent, ITreeNodeOrCompositeTreeNode } from '../../types';
import { TreeNode, CompositeTreeNode } from '../TreeNode';

Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/recycle-tree/tree/model/TreeModel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Event, Emitter } from '../../../utils';
import { Event, Emitter } from '@opensumi/ide-utils';

import { ICompositeTreeNode, TreeNodeEvent } from '../../types';
import { CompositeTreeNode, TreeNode } from '../TreeNode';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Event, Emitter, Path } from '../../../../utils';
import { Event, Emitter, path } from '@opensumi/ide-utils';

import { TreeNodeEvent, ITreeNodeOrCompositeTreeNode } from '../../../types';
import { CompositeTreeNode, TreeNode } from '../../TreeNode';

import { ISerializableState } from './types';

const { Path } = path;

export enum Operation {
SetExpanded = 1,
SetCollapsed,
Expand Down
Loading

0 comments on commit 3340fa8

Please sign in to comment.