Skip to content

Commit

Permalink
tests api implementation setup of test-item, type-converters and test…
Browse files Browse the repository at this point in the history
…ing workspace.

Signed-off-by: Zakaria Diabi  <d.zaki2396@gmail.com>
  • Loading branch information
D-Zaq authored and Zakaria committed Apr 13, 2023
1 parent c335538 commit 4ad15e0
Show file tree
Hide file tree
Showing 44 changed files with 9,525 additions and 1,596 deletions.
22 changes: 22 additions & 0 deletions packages/core/src/common/cancellation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import { Event, Emitter } from './event';
import { isBoolean, isObject } from './types';
import { Disposable } from './disposable';

export interface CancellationToken {
readonly isCancellationRequested: boolean;
Expand Down Expand Up @@ -93,11 +94,23 @@ class MutableToken implements CancellationToken {
}
return this._emitter.event;
}

public dispose(): void {
if (this._emitter) {
this._emitter.dispose();
this._emitter = undefined;
}
}
}

export class CancellationTokenSource {

private _token: CancellationToken;
private _parentListener?: Disposable = undefined;

constructor(parent?: CancellationToken) {
this._parentListener = parent && parent.onCancellationRequested(this.cancel, this);
}

get token(): CancellationToken {
if (!this._token) {
Expand All @@ -121,6 +134,15 @@ export class CancellationTokenSource {

dispose(): void {
this.cancel();
this._parentListener?.dispose();
if (!this._token) {
// ensure to initialize with an empty token if we had none
this._token = CancellationToken.None;

} else if (this._token instanceof MutableToken) {
// actually dispose
this._token.dispose();
}
}
}

Expand Down
32 changes: 32 additions & 0 deletions packages/core/src/common/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,38 @@ export namespace Event {
set maxListeners(maxListeners: number) { }
});

/**
* Given an event, returns another event which only fires once.
*/
export function once<T>(event: Event<T>): Event<T> {
return (listener, thisArgs = undefined, disposables?) => {
// we need this, in case the event fires during the listener call
let didFire = false;
let result: Disposable | undefined = undefined;
result = event(e => {
if (didFire) {
return;
} else if (result) {
result.dispose();
} else {
didFire = true;
}

return listener.call(thisArgs, e);
}, undefined, disposables);

if (didFire) {
result.dispose();
}

return result;
};
}

export function toPromise<T>(event: Event<T>): Promise<T> {
return new Promise(resolve => once(event)(resolve));
}

/**
* Given an event and a `map` function, returns another event which maps each element
* through the mapping function.
Expand Down
84 changes: 84 additions & 0 deletions packages/core/src/common/hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// *****************************************************************************
// Copyright (C) 2023 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

// based on https://github.com/microsoft/vscode/blob/04c36be045a94fee58e5f8992d3e3fd980294a84/src/vs/base/common/hash.ts

/**
* Return a hash value for an object.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function hash(obj: any): number {
return doHash(obj, 0);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function doHash(obj: any, hashVal: number): number {
switch (typeof obj) {
case 'object':
// eslint-disable-next-line no-null/no-null
if (obj === null) {
return numberHash(349, hashVal);
} else if (Array.isArray(obj)) {
return arrayHash(obj, hashVal);
}
return objectHash(obj, hashVal);
case 'string':
return stringHash(obj, hashVal);
case 'boolean':
return booleanHash(obj, hashVal);
case 'number':
return numberHash(obj, hashVal);
case 'undefined':
return numberHash(937, hashVal);
default:
return numberHash(617, hashVal);
}
}

export function numberHash(val: number, initialHashVal: number): number {
return (((initialHashVal << 5) - initialHashVal) + val) | 0; // hashVal * 31 + ch, keep as int32
}

function booleanHash(b: boolean, initialHashVal: number): number {
return numberHash(b ? 433 : 863, initialHashVal);
}

export function stringHash(s: string, hashVal: number): number {
hashVal = numberHash(149417, hashVal);
for (let i = 0, length = s.length; i < length; i++) {
hashVal = numberHash(s.charCodeAt(i), hashVal);
}
return hashVal;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function arrayHash(arr: any[], initialHashVal: number): number {
initialHashVal = numberHash(104579, initialHashVal);
return arr.reduce((hashVal, item) => doHash(item, hashVal), initialHashVal);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function objectHash(obj: any, initialHashVal: number): number {
initialHashVal = numberHash(181387, initialHashVal);
return Object.keys(obj).sort().reduce((hashVal, key) => {
hashVal = stringHash(key, hashVal);
return doHash(obj[key], hashVal);
}, initialHashVal);
}
22 changes: 22 additions & 0 deletions packages/core/src/common/markdown-rendering/markdown-string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,25 @@ export function escapeMarkdownSyntaxTokens(text: string): string {
// escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
return text.replace(/[\\`*_{}[\]()#+\-!]/g, '\\$&');
}

export function parseHrefAndDimensions(href: string): { href: string; dimensions: string[] } {
const dimensions: string[] = [];
const splitted = href.split('|').map(s => s.trim());
href = splitted[0];
const parameters = splitted[1];
if (parameters) {
const heightFromParams = /height=(\d+)/.exec(parameters);
const widthFromParams = /width=(\d+)/.exec(parameters);
const height = heightFromParams ? heightFromParams[1] : '';
const width = widthFromParams ? widthFromParams[1] : '';
const widthIsFinite = isFinite(parseInt(width));
const heightIsFinite = isFinite(parseInt(height));
if (widthIsFinite) {
dimensions.push(`width="${width}"`);
}
if (heightIsFinite) {
dimensions.push(`height="${height}"`);
}
}
return { href, dimensions };
}
46 changes: 45 additions & 1 deletion packages/core/src/common/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import { isObject } from './types';
import { isObject, isUndefinedOrNull } from './types';

export function deepClone<T>(obj: T): T {
if (!isObject(obj)) {
Expand Down Expand Up @@ -70,3 +70,47 @@ export function notEmpty<T>(arg: T | undefined | null): arg is T {
export function isEmpty(arg: Object): boolean {
return Object.keys(arg).length === 0 && arg.constructor === Object;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function cloneAndChange(obj: any, changer: (orig: any) => any): any {
return _cloneAndChange(obj, changer, new Set());
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function _cloneAndChange(obj: any, changer: (orig: any) => any, seen: Set<any>): any {
if (isUndefinedOrNull(obj)) {
return obj;
}

const changed = changer(obj);
if (typeof changed !== 'undefined') {
return changed;
}

if (Array.isArray(obj)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const r1: any[] = [];
for (const e of obj) {
r1.push(_cloneAndChange(e, changer, seen));
}
return r1;
}

if (isObject(obj)) {
if (seen.has(obj)) {
throw new Error('Cannot clone recursive data-structure');
}
seen.add(obj);
const r2 = {};
for (const i2 in obj) {
if (_hasOwnProperty.call(obj, i2)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(r2 as any)[i2] = _cloneAndChange(obj[i2], changer, seen);
}
}
seen.delete(obj);
return r2;
}

return obj;
}
9 changes: 9 additions & 0 deletions packages/core/src/common/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,12 @@ export function compareSubstringIgnoreCase(a: string, b: string, aStart: number

return 0;
}

export function regExpFlags(regexp: RegExp): string {
return (regexp.global ? 'g' : '')
+ (regexp.ignoreCase ? 'i' : '')
+ (regexp.multiline ? 'm' : '')
// eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ((regexp as any /* standalone editor compilation */).unicode ? 'u' : '');
}

15 changes: 15 additions & 0 deletions packages/core/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,18 @@ export function nullToUndefined<T>(nullable: MaybeNull<T>): MaybeUndefined<T> {
export function unreachable(_never: never, message: string = 'unhandled case'): never {
throw new Error(message);
}

/**
* @returns whether the provided parameter is defined.
*/
export function isDefined<T>(arg: T | null | undefined): arg is T {
return !isUndefinedOrNull(arg);
}

/**
* @returns whether the provided parameter is undefined or null.
*/
export function isUndefinedOrNull(obj: unknown): obj is undefined | null {
// eslint-disable-next-line no-null/no-null
return (isUndefined(obj) || obj === null);
}
98 changes: 98 additions & 0 deletions packages/core/src/common/uuid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// *****************************************************************************
// Copyright (C) 2023 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

// based on https://github.com/microsoft/vscode/blob/04c36be045a94fee58e5f8992d3e3fd980294a84/src/vs/base/common/uuid.ts

const _UUIDPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

export function isUUID(value: string): boolean {
return _UUIDPattern.test(value);
}

declare const crypto: undefined | {
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#browser_compatibility
getRandomValues?(data: Uint8Array): Uint8Array;
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID#browser_compatibility
randomUUID?(): string;
};

export const generateUuid = (function (): () => string {

// use `randomUUID` if possible
if (typeof crypto === 'object' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID.bind(crypto);
}

// use `randomValues` if possible
let getRandomValues: (bucket: Uint8Array) => Uint8Array;
if (typeof crypto === 'object' && typeof crypto.getRandomValues === 'function') {
getRandomValues = crypto.getRandomValues.bind(crypto);

} else {
getRandomValues = function (bucket: Uint8Array): Uint8Array {
for (let i = 0; i < bucket.length; i++) {
bucket[i] = Math.floor(Math.random() * 256);
}
return bucket;
};
}

// prep-work
const _data = new Uint8Array(16);
const _hex: string[] = [];
for (let i = 0; i < 256; i++) {
_hex.push(i.toString(16).padStart(2, '0'));
}

// eslint-disable-next-line @typescript-eslint/no-shadow
return function generateUuid(): string {
// get data
getRandomValues(_data);

// set version bits
_data[6] = (_data[6] & 0x0f) | 0x40;
_data[8] = (_data[8] & 0x3f) | 0x80;

// print as string
let i = 0;
let result = '';
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += '-';
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += '-';
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += '-';
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += '-';
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += _hex[_data[i++]];
result += _hex[_data[i++]];
return result;
};
})();
Loading

0 comments on commit 4ad15e0

Please sign in to comment.