mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-11 18:48:33 -05:00
SQL Operations Studio Public Preview 1 (0.23) release source code
This commit is contained in:
20
src/vs/platform/extensions/common/extensionHost.ts
Normal file
20
src/vs/platform/extensions/common/extensionHost.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Broadcast communication constants
|
||||
|
||||
export const EXTENSION_LOG_BROADCAST_CHANNEL = 'vscode:extensionLog';
|
||||
export const EXTENSION_ATTACH_BROADCAST_CHANNEL = 'vscode:extensionAttach';
|
||||
export const EXTENSION_TERMINATE_BROADCAST_CHANNEL = 'vscode:extensionTerminate';
|
||||
export const EXTENSION_RELOAD_BROADCAST_CHANNEL = 'vscode:extensionReload';
|
||||
export const EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL = 'vscode:extensionCloseExtensionHost';
|
||||
|
||||
export interface ILogEntry {
|
||||
type: string;
|
||||
severity: string;
|
||||
arguments: any;
|
||||
}
|
||||
105
src/vs/platform/extensions/common/extensions.ts
Normal file
105
src/vs/platform/extensions/common/extensions.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionPoint } from 'vs/platform/extensions/common/extensionsRegistry';
|
||||
|
||||
export interface IExtensionDescription {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly displayName?: string;
|
||||
readonly version: string;
|
||||
readonly publisher: string;
|
||||
readonly isBuiltin: boolean;
|
||||
readonly extensionFolderPath: string;
|
||||
readonly extensionDependencies?: string[];
|
||||
readonly activationEvents?: string[];
|
||||
readonly engines: {
|
||||
vscode: string;
|
||||
};
|
||||
readonly main?: string;
|
||||
readonly contributes?: { [point: string]: any; };
|
||||
enableProposedApi?: boolean;
|
||||
}
|
||||
|
||||
export const IExtensionService = createDecorator<IExtensionService>('extensionService');
|
||||
|
||||
export interface IMessage {
|
||||
type: Severity;
|
||||
message: string;
|
||||
source: string;
|
||||
extensionId: string;
|
||||
extensionPointId: string;
|
||||
}
|
||||
|
||||
export interface IExtensionsStatus {
|
||||
messages: IMessage[];
|
||||
}
|
||||
|
||||
export class ActivationTimes {
|
||||
public readonly startup: boolean;
|
||||
public readonly codeLoadingTime: number;
|
||||
public readonly activateCallTime: number;
|
||||
public readonly activateResolvedTime: number;
|
||||
|
||||
constructor(startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number) {
|
||||
this.startup = startup;
|
||||
this.codeLoadingTime = codeLoadingTime;
|
||||
this.activateCallTime = activateCallTime;
|
||||
this.activateResolvedTime = activateResolvedTime;
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtensionPointContribution<T> {
|
||||
readonly description: IExtensionDescription;
|
||||
readonly value: T;
|
||||
|
||||
constructor(description: IExtensionDescription, value: T) {
|
||||
this.description = description;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IExtensionService {
|
||||
_serviceBrand: any;
|
||||
|
||||
/**
|
||||
* Send an activation event and activate interested extensions.
|
||||
*/
|
||||
activateByEvent(activationEvent: string): TPromise<void>;
|
||||
|
||||
/**
|
||||
* Block on this signal any interactions with extensions.
|
||||
*/
|
||||
onReady(): TPromise<boolean>;
|
||||
|
||||
/**
|
||||
* Return all registered extensions
|
||||
*/
|
||||
getExtensions(): TPromise<IExtensionDescription[]>;
|
||||
|
||||
/**
|
||||
* Read all contributions to an extension point.
|
||||
*/
|
||||
readExtensionPointContributions<T>(extPoint: IExtensionPoint<T>): TPromise<ExtensionPointContribution<T>[]>;
|
||||
|
||||
/**
|
||||
* Get information about extensions status.
|
||||
*/
|
||||
getExtensionsStatus(): { [id: string]: IExtensionsStatus };
|
||||
|
||||
/**
|
||||
* Get information about extension activation times.
|
||||
*/
|
||||
getExtensionsActivationTimes(): { [id: string]: ActivationTimes; };
|
||||
|
||||
/**
|
||||
* Restarts the extension host.
|
||||
*/
|
||||
restartExtensionHost(): void;
|
||||
}
|
||||
297
src/vs/platform/extensions/common/extensionsRegistry.ts
Normal file
297
src/vs/platform/extensions/common/extensionsRegistry.ts
Normal file
@@ -0,0 +1,297 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IMessage, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Extensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
|
||||
const hasOwnProperty = Object.hasOwnProperty;
|
||||
const schemaRegistry = <IJSONContributionRegistry>Registry.as(Extensions.JSONContribution);
|
||||
|
||||
export class ExtensionMessageCollector {
|
||||
|
||||
private readonly _messageHandler: (msg: IMessage) => void;
|
||||
private readonly _extension: IExtensionDescription;
|
||||
private readonly _extensionPointId: string;
|
||||
|
||||
constructor(
|
||||
messageHandler: (msg: IMessage) => void,
|
||||
extension: IExtensionDescription,
|
||||
extensionPointId: string
|
||||
) {
|
||||
this._messageHandler = messageHandler;
|
||||
this._extension = extension;
|
||||
this._extensionPointId = extensionPointId;
|
||||
}
|
||||
|
||||
private _msg(type: Severity, message: string): void {
|
||||
this._messageHandler({
|
||||
type: type,
|
||||
message: message,
|
||||
source: this._extension.extensionFolderPath,
|
||||
extensionId: this._extension.id,
|
||||
extensionPointId: this._extensionPointId
|
||||
});
|
||||
}
|
||||
|
||||
public error(message: string): void {
|
||||
this._msg(Severity.Error, message);
|
||||
}
|
||||
|
||||
public warn(message: string): void {
|
||||
this._msg(Severity.Warning, message);
|
||||
}
|
||||
|
||||
public info(message: string): void {
|
||||
this._msg(Severity.Info, message);
|
||||
}
|
||||
}
|
||||
|
||||
export interface IExtensionPointUser<T> {
|
||||
description: IExtensionDescription;
|
||||
value: T;
|
||||
collector: ExtensionMessageCollector;
|
||||
}
|
||||
|
||||
export interface IExtensionPointHandler<T> {
|
||||
(extensions: IExtensionPointUser<T>[]): void;
|
||||
}
|
||||
|
||||
export interface IExtensionPoint<T> {
|
||||
name: string;
|
||||
setHandler(handler: IExtensionPointHandler<T>): void;
|
||||
}
|
||||
|
||||
export class ExtensionPoint<T> implements IExtensionPoint<T> {
|
||||
|
||||
public readonly name: string;
|
||||
private _handler: IExtensionPointHandler<T>;
|
||||
private _users: IExtensionPointUser<T>[];
|
||||
private _done: boolean;
|
||||
|
||||
constructor(name: string) {
|
||||
this.name = name;
|
||||
this._handler = null;
|
||||
this._users = null;
|
||||
this._done = false;
|
||||
}
|
||||
|
||||
setHandler(handler: IExtensionPointHandler<T>): void {
|
||||
if (this._handler !== null || this._done) {
|
||||
throw new Error('Handler already set!');
|
||||
}
|
||||
this._handler = handler;
|
||||
this._handle();
|
||||
}
|
||||
|
||||
acceptUsers(users: IExtensionPointUser<T>[]): void {
|
||||
if (this._users !== null || this._done) {
|
||||
throw new Error('Users already set!');
|
||||
}
|
||||
this._users = users;
|
||||
this._handle();
|
||||
}
|
||||
|
||||
private _handle(): void {
|
||||
if (this._handler === null || this._users === null) {
|
||||
return;
|
||||
}
|
||||
this._done = true;
|
||||
|
||||
let handler = this._handler;
|
||||
this._handler = null;
|
||||
|
||||
let users = this._users;
|
||||
this._users = null;
|
||||
|
||||
try {
|
||||
handler(users);
|
||||
} catch (err) {
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaId = 'vscode://schemas/vscode-extensions';
|
||||
const schema: IJSONSchema = {
|
||||
properties: {
|
||||
engines: {
|
||||
type: 'object',
|
||||
|
||||
properties: {
|
||||
'vscode': {
|
||||
type: 'string',
|
||||
description: nls.localize('vscode.extension.engines.vscode', 'For VS Code extensions, specifies the VS Code version that the extension is compatible with. Cannot be *. For example: ^0.10.5 indicates compatibility with a minimum VS Code version of 0.10.5.'),
|
||||
default: '^0.10.0',
|
||||
}
|
||||
}
|
||||
},
|
||||
publisher: {
|
||||
description: nls.localize('vscode.extension.publisher', 'The publisher of the VS Code extension.'),
|
||||
type: 'string'
|
||||
},
|
||||
displayName: {
|
||||
description: nls.localize('vscode.extension.displayName', 'The display name for the extension used in the VS Code gallery.'),
|
||||
type: 'string'
|
||||
},
|
||||
categories: {
|
||||
description: nls.localize('vscode.extension.categories', 'The categories used by the VS Code gallery to categorize the extension.'),
|
||||
type: 'array',
|
||||
uniqueItems: true,
|
||||
items: {
|
||||
type: 'string',
|
||||
enum: ['Languages', 'Snippets', 'Linters', 'Themes', 'Debuggers', 'Other', 'Keymaps', 'Formatters', 'Extension Packs', 'SCM Providers', 'Azure']
|
||||
}
|
||||
},
|
||||
galleryBanner: {
|
||||
type: 'object',
|
||||
description: nls.localize('vscode.extension.galleryBanner', 'Banner used in the VS Code marketplace.'),
|
||||
properties: {
|
||||
color: {
|
||||
description: nls.localize('vscode.extension.galleryBanner.color', 'The banner color on the VS Code marketplace page header.'),
|
||||
type: 'string'
|
||||
},
|
||||
theme: {
|
||||
description: nls.localize('vscode.extension.galleryBanner.theme', 'The color theme for the font used in the banner.'),
|
||||
type: 'string',
|
||||
enum: ['dark', 'light']
|
||||
}
|
||||
}
|
||||
},
|
||||
contributes: {
|
||||
description: nls.localize('vscode.extension.contributes', 'All contributions of the VS Code extension represented by this package.'),
|
||||
type: 'object',
|
||||
properties: {
|
||||
// extensions will fill in
|
||||
},
|
||||
default: {}
|
||||
},
|
||||
preview: {
|
||||
type: 'boolean',
|
||||
description: nls.localize('vscode.extension.preview', 'Sets the extension to be flagged as a Preview in the Marketplace.'),
|
||||
},
|
||||
activationEvents: {
|
||||
description: nls.localize('vscode.extension.activationEvents', 'Activation events for the VS Code extension.'),
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
defaultSnippets: [
|
||||
{
|
||||
label: 'onLanguage',
|
||||
description: nls.localize('vscode.extension.activationEvents.onLanguage', 'An activation event emitted whenever a file that resolves to the specified language gets opened.'),
|
||||
body: 'onLanguage:${1:languageId}'
|
||||
},
|
||||
{
|
||||
label: 'onCommand',
|
||||
description: nls.localize('vscode.extension.activationEvents.onCommand', 'An activation event emitted whenever the specified command gets invoked.'),
|
||||
body: 'onCommand:${2:commandId}'
|
||||
},
|
||||
{
|
||||
label: 'onDebug',
|
||||
description: nls.localize('vscode.extension.activationEvents.onDebug', 'An activation event emitted whenever a debug session of the specified type is started.'),
|
||||
body: 'onDebug:${3:type}'
|
||||
},
|
||||
{
|
||||
label: 'workspaceContains',
|
||||
description: nls.localize('vscode.extension.activationEvents.workspaceContains', 'An activation event emitted whenever a folder is opened that contains at least a file matching the specified glob pattern.'),
|
||||
body: 'workspaceContains:${4:filePattern}'
|
||||
},
|
||||
{
|
||||
label: 'onView',
|
||||
body: 'onView:${5:viewId}',
|
||||
description: nls.localize('vscode.extension.activationEvents.onView', 'An activation event emitted whenever the specified view is expanded.'),
|
||||
},
|
||||
{
|
||||
label: '*',
|
||||
description: nls.localize('vscode.extension.activationEvents.star', 'An activation event emitted on VS Code startup. To ensure a great end user experience, please use this activation event in your extension only when no other activation events combination works in your use-case.'),
|
||||
body: '*'
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
badges: {
|
||||
type: 'array',
|
||||
description: nls.localize('vscode.extension.badges', 'Array of badges to display in the sidebar of the Marketplace\'s extension page.'),
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['url', 'href', 'description'],
|
||||
properties: {
|
||||
url: {
|
||||
type: 'string',
|
||||
description: nls.localize('vscode.extension.badges.url', 'Badge image URL.')
|
||||
},
|
||||
href: {
|
||||
type: 'string',
|
||||
description: nls.localize('vscode.extension.badges.href', 'Badge link.')
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: nls.localize('vscode.extension.badges.description', 'Badge description.')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
extensionDependencies: {
|
||||
description: nls.localize('vscode.extension.extensionDependencies', 'Dependencies to other extensions. The identifier of an extension is always ${publisher}.${name}. For example: vscode.csharp.'),
|
||||
type: 'array',
|
||||
uniqueItems: true,
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
scripts: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
'vscode:prepublish': {
|
||||
description: nls.localize('vscode.extension.scripts.prepublish', 'Script executed before the package is published as a VS Code extension.'),
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
description: nls.localize('vscode.extension.icon', 'The path to a 128x128 pixel icon.')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export class ExtensionsRegistryImpl {
|
||||
|
||||
private _extensionPoints: { [extPoint: string]: ExtensionPoint<any>; };
|
||||
|
||||
constructor() {
|
||||
this._extensionPoints = {};
|
||||
}
|
||||
|
||||
public registerExtensionPoint<T>(extensionPoint: string, deps: IExtensionPoint<any>[], jsonSchema: IJSONSchema): IExtensionPoint<T> {
|
||||
if (hasOwnProperty.call(this._extensionPoints, extensionPoint)) {
|
||||
throw new Error('Duplicate extension point: ' + extensionPoint);
|
||||
}
|
||||
let result = new ExtensionPoint<T>(extensionPoint);
|
||||
this._extensionPoints[extensionPoint] = result;
|
||||
|
||||
schema.properties['contributes'].properties[extensionPoint] = jsonSchema;
|
||||
schemaRegistry.registerSchema(schemaId, schema);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public getExtensionPoints(): ExtensionPoint<any>[] {
|
||||
return Object.keys(this._extensionPoints).map(point => this._extensionPoints[point]);
|
||||
}
|
||||
}
|
||||
|
||||
const PRExtensions = {
|
||||
ExtensionsRegistry: 'ExtensionsRegistry'
|
||||
};
|
||||
Registry.add(PRExtensions.ExtensionsRegistry, new ExtensionsRegistryImpl());
|
||||
export const ExtensionsRegistry: ExtensionsRegistryImpl = Registry.as(PRExtensions.ExtensionsRegistry);
|
||||
|
||||
schemaRegistry.registerSchema(schemaId, schema);
|
||||
343
src/vs/platform/extensions/node/extensionValidator.ts
Normal file
343
src/vs/platform/extensions/node/extensionValidator.ts
Normal file
@@ -0,0 +1,343 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { valid } from 'semver';
|
||||
import { join } from 'path';
|
||||
|
||||
export interface IParsedVersion {
|
||||
hasCaret: boolean;
|
||||
hasGreaterEquals: boolean;
|
||||
majorBase: number;
|
||||
majorMustEqual: boolean;
|
||||
minorBase: number;
|
||||
minorMustEqual: boolean;
|
||||
patchBase: number;
|
||||
patchMustEqual: boolean;
|
||||
preRelease: string;
|
||||
}
|
||||
|
||||
export interface INormalizedVersion {
|
||||
majorBase: number;
|
||||
majorMustEqual: boolean;
|
||||
minorBase: number;
|
||||
minorMustEqual: boolean;
|
||||
patchBase: number;
|
||||
patchMustEqual: boolean;
|
||||
isMinimum: boolean;
|
||||
}
|
||||
|
||||
const VERSION_REGEXP = /^(\^|>=)?((\d+)|x)\.((\d+)|x)\.((\d+)|x)(\-.*)?$/;
|
||||
|
||||
export function isValidVersionStr(version: string): boolean {
|
||||
version = version.trim();
|
||||
return (version === '*' || VERSION_REGEXP.test(version));
|
||||
}
|
||||
|
||||
export function parseVersion(version: string): IParsedVersion {
|
||||
if (!isValidVersionStr(version)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
version = version.trim();
|
||||
|
||||
if (version === '*') {
|
||||
return {
|
||||
hasCaret: false,
|
||||
hasGreaterEquals: false,
|
||||
majorBase: 0,
|
||||
majorMustEqual: false,
|
||||
minorBase: 0,
|
||||
minorMustEqual: false,
|
||||
patchBase: 0,
|
||||
patchMustEqual: false,
|
||||
preRelease: null
|
||||
};
|
||||
}
|
||||
|
||||
let m = version.match(VERSION_REGEXP);
|
||||
return {
|
||||
hasCaret: m[1] === '^',
|
||||
hasGreaterEquals: m[1] === '>=',
|
||||
majorBase: m[2] === 'x' ? 0 : parseInt(m[2], 10),
|
||||
majorMustEqual: (m[2] === 'x' ? false : true),
|
||||
minorBase: m[4] === 'x' ? 0 : parseInt(m[4], 10),
|
||||
minorMustEqual: (m[4] === 'x' ? false : true),
|
||||
patchBase: m[6] === 'x' ? 0 : parseInt(m[6], 10),
|
||||
patchMustEqual: (m[6] === 'x' ? false : true),
|
||||
preRelease: m[8] || null
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeVersion(version: IParsedVersion): INormalizedVersion {
|
||||
if (!version) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let majorBase = version.majorBase,
|
||||
majorMustEqual = version.majorMustEqual,
|
||||
minorBase = version.minorBase,
|
||||
minorMustEqual = version.minorMustEqual,
|
||||
patchBase = version.patchBase,
|
||||
patchMustEqual = version.patchMustEqual;
|
||||
|
||||
if (version.hasCaret) {
|
||||
if (majorBase === 0) {
|
||||
patchMustEqual = false;
|
||||
} else {
|
||||
minorMustEqual = false;
|
||||
patchMustEqual = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
majorBase: majorBase,
|
||||
majorMustEqual: majorMustEqual,
|
||||
minorBase: minorBase,
|
||||
minorMustEqual: minorMustEqual,
|
||||
patchBase: patchBase,
|
||||
patchMustEqual: patchMustEqual,
|
||||
isMinimum: version.hasGreaterEquals
|
||||
};
|
||||
}
|
||||
|
||||
export function isValidVersion(_version: string | INormalizedVersion, _desiredVersion: string | INormalizedVersion): boolean {
|
||||
let version: INormalizedVersion;
|
||||
if (typeof _version === 'string') {
|
||||
version = normalizeVersion(parseVersion(_version));
|
||||
} else {
|
||||
version = _version;
|
||||
}
|
||||
|
||||
let desiredVersion: INormalizedVersion;
|
||||
if (typeof _desiredVersion === 'string') {
|
||||
desiredVersion = normalizeVersion(parseVersion(_desiredVersion));
|
||||
} else {
|
||||
desiredVersion = _desiredVersion;
|
||||
}
|
||||
|
||||
if (!version || !desiredVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let majorBase = version.majorBase;
|
||||
let minorBase = version.minorBase;
|
||||
let patchBase = version.patchBase;
|
||||
|
||||
let desiredMajorBase = desiredVersion.majorBase;
|
||||
let desiredMinorBase = desiredVersion.minorBase;
|
||||
let desiredPatchBase = desiredVersion.patchBase;
|
||||
|
||||
let majorMustEqual = desiredVersion.majorMustEqual;
|
||||
let minorMustEqual = desiredVersion.minorMustEqual;
|
||||
let patchMustEqual = desiredVersion.patchMustEqual;
|
||||
|
||||
if (desiredVersion.isMinimum) {
|
||||
if (majorBase > desiredMajorBase) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (majorBase < desiredMajorBase) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (minorBase > desiredMinorBase) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (minorBase < desiredMinorBase) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return patchBase >= desiredPatchBase;
|
||||
}
|
||||
|
||||
// Anything < 1.0.0 is compatible with >= 1.0.0, except exact matches
|
||||
if (majorBase === 1 && desiredMajorBase === 0 && (!majorMustEqual || !minorMustEqual || !patchMustEqual)) {
|
||||
desiredMajorBase = 1;
|
||||
desiredMinorBase = 0;
|
||||
desiredPatchBase = 0;
|
||||
majorMustEqual = true;
|
||||
minorMustEqual = false;
|
||||
patchMustEqual = false;
|
||||
}
|
||||
|
||||
if (majorBase < desiredMajorBase) {
|
||||
// smaller major version
|
||||
return false;
|
||||
}
|
||||
|
||||
if (majorBase > desiredMajorBase) {
|
||||
// higher major version
|
||||
return (!majorMustEqual);
|
||||
}
|
||||
|
||||
// at this point, majorBase are equal
|
||||
|
||||
if (minorBase < desiredMinorBase) {
|
||||
// smaller minor version
|
||||
return false;
|
||||
}
|
||||
|
||||
if (minorBase > desiredMinorBase) {
|
||||
// higher minor version
|
||||
return (!minorMustEqual);
|
||||
}
|
||||
|
||||
// at this point, minorBase are equal
|
||||
|
||||
if (patchBase < desiredPatchBase) {
|
||||
// smaller patch version
|
||||
return false;
|
||||
}
|
||||
|
||||
if (patchBase > desiredPatchBase) {
|
||||
// higher patch version
|
||||
return (!patchMustEqual);
|
||||
}
|
||||
|
||||
// at this point, patchBase are equal
|
||||
return true;
|
||||
}
|
||||
|
||||
export interface IReducedExtensionDescription {
|
||||
isBuiltin: boolean;
|
||||
engines: {
|
||||
vscode: string;
|
||||
};
|
||||
main?: string;
|
||||
}
|
||||
|
||||
export function isValidExtensionVersion(version: string, extensionDesc: IReducedExtensionDescription, notices: string[]): boolean {
|
||||
|
||||
if (extensionDesc.isBuiltin || typeof extensionDesc.main === 'undefined') {
|
||||
// No version check for builtin or declarative extensions
|
||||
return true;
|
||||
}
|
||||
|
||||
return isVersionValid(version, extensionDesc.engines.vscode, notices);
|
||||
}
|
||||
|
||||
export function isVersionValid(currentVersion: string, requestedVersion: string, notices: string[] = []): boolean {
|
||||
|
||||
let desiredVersion = normalizeVersion(parseVersion(requestedVersion));
|
||||
if (!desiredVersion) {
|
||||
notices.push(nls.localize('versionSyntax', "Could not parse `engines.vscode` value {0}. Please use, for example: ^0.10.0, ^1.2.3, ^0.11.0, ^0.10.x, etc.", requestedVersion));
|
||||
return false;
|
||||
}
|
||||
|
||||
// enforce that a breaking API version is specified.
|
||||
// for 0.X.Y, that means up to 0.X must be specified
|
||||
// otherwise for Z.X.Y, that means Z must be specified
|
||||
if (desiredVersion.majorBase === 0) {
|
||||
// force that major and minor must be specific
|
||||
if (!desiredVersion.majorMustEqual || !desiredVersion.minorMustEqual) {
|
||||
notices.push(nls.localize('versionSpecificity1', "Version specified in `engines.vscode` ({0}) is not specific enough. For vscode versions before 1.0.0, please define at a minimum the major and minor desired version. E.g. ^0.10.0, 0.10.x, 0.11.0, etc.", requestedVersion));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// force that major must be specific
|
||||
if (!desiredVersion.majorMustEqual) {
|
||||
notices.push(nls.localize('versionSpecificity2', "Version specified in `engines.vscode` ({0}) is not specific enough. For vscode versions after 1.0.0, please define at a minimum the major desired version. E.g. ^1.10.0, 1.10.x, 1.x.x, 2.x.x, etc.", requestedVersion));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValidVersion(currentVersion, desiredVersion)) {
|
||||
notices.push(nls.localize('versionMismatch', "Extension is not compatible with Code {0}. Extension requires: {1}.", currentVersion, requestedVersion));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function _isStringArray(arr: string[]): boolean {
|
||||
if (!Array.isArray(arr)) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
if (typeof arr[i] !== 'string') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function baseIsValidExtensionDescription(extensionFolderPath: string, extensionDescription: IExtensionDescription, notices: string[]): boolean {
|
||||
if (!extensionDescription) {
|
||||
notices.push(nls.localize('extensionDescription.empty', "Got empty extension description"));
|
||||
return false;
|
||||
}
|
||||
if (typeof extensionDescription.publisher !== 'string') {
|
||||
notices.push(nls.localize('extensionDescription.publisher', "property `{0}` is mandatory and must be of type `string`", 'publisher'));
|
||||
return false;
|
||||
}
|
||||
if (typeof extensionDescription.name !== 'string') {
|
||||
notices.push(nls.localize('extensionDescription.name', "property `{0}` is mandatory and must be of type `string`", 'name'));
|
||||
return false;
|
||||
}
|
||||
if (typeof extensionDescription.version !== 'string') {
|
||||
notices.push(nls.localize('extensionDescription.version', "property `{0}` is mandatory and must be of type `string`", 'version'));
|
||||
return false;
|
||||
}
|
||||
if (!extensionDescription.engines) {
|
||||
notices.push(nls.localize('extensionDescription.engines', "property `{0}` is mandatory and must be of type `object`", 'engines'));
|
||||
return false;
|
||||
}
|
||||
if (typeof extensionDescription.engines.vscode !== 'string') {
|
||||
notices.push(nls.localize('extensionDescription.engines.vscode', "property `{0}` is mandatory and must be of type `string`", 'engines.vscode'));
|
||||
return false;
|
||||
}
|
||||
if (typeof extensionDescription.extensionDependencies !== 'undefined') {
|
||||
if (!_isStringArray(extensionDescription.extensionDependencies)) {
|
||||
notices.push(nls.localize('extensionDescription.extensionDependencies', "property `{0}` can be omitted or must be of type `string[]`", 'extensionDependencies'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (typeof extensionDescription.activationEvents !== 'undefined') {
|
||||
if (!_isStringArray(extensionDescription.activationEvents)) {
|
||||
notices.push(nls.localize('extensionDescription.activationEvents1', "property `{0}` can be omitted or must be of type `string[]`", 'activationEvents'));
|
||||
return false;
|
||||
}
|
||||
if (typeof extensionDescription.main === 'undefined') {
|
||||
notices.push(nls.localize('extensionDescription.activationEvents2', "properties `{0}` and `{1}` must both be specified or must both be omitted", 'activationEvents', 'main'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (typeof extensionDescription.main !== 'undefined') {
|
||||
if (typeof extensionDescription.main !== 'string') {
|
||||
notices.push(nls.localize('extensionDescription.main1', "property `{0}` can be omitted or must be of type `string`", 'main'));
|
||||
return false;
|
||||
} else {
|
||||
let normalizedAbsolutePath = join(extensionFolderPath, extensionDescription.main);
|
||||
|
||||
if (normalizedAbsolutePath.indexOf(extensionFolderPath)) {
|
||||
notices.push(nls.localize('extensionDescription.main2', "Expected `main` ({0}) to be included inside extension's folder ({1}). This might make the extension non-portable.", normalizedAbsolutePath, extensionFolderPath));
|
||||
// not a failure case
|
||||
}
|
||||
}
|
||||
if (typeof extensionDescription.activationEvents === 'undefined') {
|
||||
notices.push(nls.localize('extensionDescription.main3', "properties `{0}` and `{1}` must both be specified or must both be omitted", 'activationEvents', 'main'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isValidExtensionDescription(version: string, extensionFolderPath: string, extensionDescription: IExtensionDescription, notices: string[]): boolean {
|
||||
|
||||
if (!baseIsValidExtensionDescription(extensionFolderPath, extensionDescription, notices)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!valid(extensionDescription.version)) {
|
||||
notices.push(nls.localize('notSemver', "Extension version is not semver compatible."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return isValidExtensionVersion(version, extensionDescription, notices);
|
||||
}
|
||||
396
src/vs/platform/extensions/test/node/extensionValidator.test.ts
Normal file
396
src/vs/platform/extensions/test/node/extensionValidator.test.ts
Normal file
@@ -0,0 +1,396 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { INormalizedVersion, IParsedVersion, IReducedExtensionDescription, isValidExtensionVersion, isValidVersion, isValidVersionStr, normalizeVersion, parseVersion } from 'vs/platform/extensions/node/extensionValidator';
|
||||
|
||||
suite('Extension Version Validator', () => {
|
||||
|
||||
test('isValidVersionStr', () => {
|
||||
assert.equal(isValidVersionStr('0.10.0-dev'), true);
|
||||
assert.equal(isValidVersionStr('0.10.0'), true);
|
||||
assert.equal(isValidVersionStr('0.10.1'), true);
|
||||
assert.equal(isValidVersionStr('0.10.100'), true);
|
||||
assert.equal(isValidVersionStr('0.11.0'), true);
|
||||
|
||||
assert.equal(isValidVersionStr('x.x.x'), true);
|
||||
assert.equal(isValidVersionStr('0.x.x'), true);
|
||||
assert.equal(isValidVersionStr('0.10.0'), true);
|
||||
assert.equal(isValidVersionStr('0.10.x'), true);
|
||||
assert.equal(isValidVersionStr('^0.10.0'), true);
|
||||
assert.equal(isValidVersionStr('*'), true);
|
||||
|
||||
assert.equal(isValidVersionStr('0.x.x.x'), false);
|
||||
assert.equal(isValidVersionStr('0.10'), false);
|
||||
assert.equal(isValidVersionStr('0.10.'), false);
|
||||
});
|
||||
|
||||
test('parseVersion', () => {
|
||||
function assertParseVersion(version: string, hasCaret: boolean, hasGreaterEquals: boolean, majorBase: number, majorMustEqual: boolean, minorBase: number, minorMustEqual: boolean, patchBase: number, patchMustEqual: boolean, preRelease: string): void {
|
||||
const actual = parseVersion(version);
|
||||
const expected: IParsedVersion = { hasCaret, hasGreaterEquals, majorBase, majorMustEqual, minorBase, minorMustEqual, patchBase, patchMustEqual, preRelease };
|
||||
|
||||
assert.deepEqual(actual, expected, 'parseVersion for ' + version);
|
||||
}
|
||||
|
||||
assertParseVersion('0.10.0-dev', false, false, 0, true, 10, true, 0, true, '-dev');
|
||||
assertParseVersion('0.10.0', false, false, 0, true, 10, true, 0, true, null);
|
||||
assertParseVersion('0.10.1', false, false, 0, true, 10, true, 1, true, null);
|
||||
assertParseVersion('0.10.100', false, false, 0, true, 10, true, 100, true, null);
|
||||
assertParseVersion('0.11.0', false, false, 0, true, 11, true, 0, true, null);
|
||||
|
||||
assertParseVersion('x.x.x', false, false, 0, false, 0, false, 0, false, null);
|
||||
assertParseVersion('0.x.x', false, false, 0, true, 0, false, 0, false, null);
|
||||
assertParseVersion('0.10.x', false, false, 0, true, 10, true, 0, false, null);
|
||||
assertParseVersion('^0.10.0', true, false, 0, true, 10, true, 0, true, null);
|
||||
assertParseVersion('^0.10.2', true, false, 0, true, 10, true, 2, true, null);
|
||||
assertParseVersion('^1.10.2', true, false, 1, true, 10, true, 2, true, null);
|
||||
assertParseVersion('*', false, false, 0, false, 0, false, 0, false, null);
|
||||
|
||||
assertParseVersion('>=0.0.1', false, true, 0, true, 0, true, 1, true, null);
|
||||
assertParseVersion('>=2.4.3', false, true, 2, true, 4, true, 3, true, null);
|
||||
});
|
||||
|
||||
test('normalizeVersion', () => {
|
||||
function assertNormalizeVersion(version: string, majorBase: number, majorMustEqual: boolean, minorBase: number, minorMustEqual: boolean, patchBase: number, patchMustEqual: boolean, isMinimum: boolean): void {
|
||||
const actual = normalizeVersion(parseVersion(version));
|
||||
const expected: INormalizedVersion = { majorBase, majorMustEqual, minorBase, minorMustEqual, patchBase, patchMustEqual, isMinimum };
|
||||
assert.deepEqual(actual, expected, 'parseVersion for ' + version);
|
||||
}
|
||||
|
||||
assertNormalizeVersion('0.10.0-dev', 0, true, 10, true, 0, true, false);
|
||||
assertNormalizeVersion('0.10.0', 0, true, 10, true, 0, true, false);
|
||||
assertNormalizeVersion('0.10.1', 0, true, 10, true, 1, true, false);
|
||||
assertNormalizeVersion('0.10.100', 0, true, 10, true, 100, true, false);
|
||||
assertNormalizeVersion('0.11.0', 0, true, 11, true, 0, true, false);
|
||||
|
||||
assertNormalizeVersion('x.x.x', 0, false, 0, false, 0, false, false);
|
||||
assertNormalizeVersion('0.x.x', 0, true, 0, false, 0, false, false);
|
||||
assertNormalizeVersion('0.10.x', 0, true, 10, true, 0, false, false);
|
||||
assertNormalizeVersion('^0.10.0', 0, true, 10, true, 0, false, false);
|
||||
assertNormalizeVersion('^0.10.2', 0, true, 10, true, 2, false, false);
|
||||
assertNormalizeVersion('^1.10.2', 1, true, 10, false, 2, false, false);
|
||||
assertNormalizeVersion('*', 0, false, 0, false, 0, false, false);
|
||||
|
||||
assertNormalizeVersion('>=0.0.1', 0, true, 0, true, 1, true, true);
|
||||
assertNormalizeVersion('>=2.4.3', 2, true, 4, true, 3, true, true);
|
||||
});
|
||||
|
||||
test('isValidVersion', () => {
|
||||
function testIsValidVersion(version: string, desiredVersion: string, expectedResult: boolean): void {
|
||||
let actual = isValidVersion(version, desiredVersion);
|
||||
assert.equal(actual, expectedResult, 'extension - vscode: ' + version + ', desiredVersion: ' + desiredVersion + ' should be ' + expectedResult);
|
||||
}
|
||||
|
||||
testIsValidVersion('0.10.0-dev', 'x.x.x', true);
|
||||
testIsValidVersion('0.10.0-dev', '0.x.x', true);
|
||||
testIsValidVersion('0.10.0-dev', '0.10.0', true);
|
||||
testIsValidVersion('0.10.0-dev', '0.10.2', false);
|
||||
testIsValidVersion('0.10.0-dev', '^0.10.2', false);
|
||||
testIsValidVersion('0.10.0-dev', '0.10.x', true);
|
||||
testIsValidVersion('0.10.0-dev', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.0-dev', '*', true);
|
||||
testIsValidVersion('0.10.0-dev', '>=0.0.1', true);
|
||||
testIsValidVersion('0.10.0-dev', '>=0.0.10', true);
|
||||
testIsValidVersion('0.10.0-dev', '>=0.10.0', true);
|
||||
testIsValidVersion('0.10.0-dev', '>=0.10.1', false);
|
||||
testIsValidVersion('0.10.0-dev', '>=1.0.0', false);
|
||||
|
||||
testIsValidVersion('0.10.0', 'x.x.x', true);
|
||||
testIsValidVersion('0.10.0', '0.x.x', true);
|
||||
testIsValidVersion('0.10.0', '0.10.0', true);
|
||||
testIsValidVersion('0.10.0', '0.10.2', false);
|
||||
testIsValidVersion('0.10.0', '^0.10.2', false);
|
||||
testIsValidVersion('0.10.0', '0.10.x', true);
|
||||
testIsValidVersion('0.10.0', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.0', '*', true);
|
||||
|
||||
testIsValidVersion('0.10.1', 'x.x.x', true);
|
||||
testIsValidVersion('0.10.1', '0.x.x', true);
|
||||
testIsValidVersion('0.10.1', '0.10.0', false);
|
||||
testIsValidVersion('0.10.1', '0.10.2', false);
|
||||
testIsValidVersion('0.10.1', '^0.10.2', false);
|
||||
testIsValidVersion('0.10.1', '0.10.x', true);
|
||||
testIsValidVersion('0.10.1', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.1', '*', true);
|
||||
|
||||
testIsValidVersion('0.10.100', 'x.x.x', true);
|
||||
testIsValidVersion('0.10.100', '0.x.x', true);
|
||||
testIsValidVersion('0.10.100', '0.10.0', false);
|
||||
testIsValidVersion('0.10.100', '0.10.2', false);
|
||||
testIsValidVersion('0.10.100', '^0.10.2', true);
|
||||
testIsValidVersion('0.10.100', '0.10.x', true);
|
||||
testIsValidVersion('0.10.100', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.100', '*', true);
|
||||
|
||||
testIsValidVersion('0.11.0', 'x.x.x', true);
|
||||
testIsValidVersion('0.11.0', '0.x.x', true);
|
||||
testIsValidVersion('0.11.0', '0.10.0', false);
|
||||
testIsValidVersion('0.11.0', '0.10.2', false);
|
||||
testIsValidVersion('0.11.0', '^0.10.2', false);
|
||||
testIsValidVersion('0.11.0', '0.10.x', false);
|
||||
testIsValidVersion('0.11.0', '^0.10.0', false);
|
||||
testIsValidVersion('0.11.0', '*', true);
|
||||
|
||||
// Anything < 1.0.0 is compatible
|
||||
|
||||
testIsValidVersion('1.0.0', 'x.x.x', true);
|
||||
testIsValidVersion('1.0.0', '0.x.x', true);
|
||||
testIsValidVersion('1.0.0', '0.10.0', false);
|
||||
testIsValidVersion('1.0.0', '0.10.2', false);
|
||||
testIsValidVersion('1.0.0', '^0.10.2', true);
|
||||
testIsValidVersion('1.0.0', '0.10.x', true);
|
||||
testIsValidVersion('1.0.0', '^0.10.0', true);
|
||||
testIsValidVersion('1.0.0', '1.0.0', true);
|
||||
testIsValidVersion('1.0.0', '^1.0.0', true);
|
||||
testIsValidVersion('1.0.0', '^2.0.0', false);
|
||||
testIsValidVersion('1.0.0', '*', true);
|
||||
testIsValidVersion('1.0.0', '>=0.0.1', true);
|
||||
testIsValidVersion('1.0.0', '>=0.0.10', true);
|
||||
testIsValidVersion('1.0.0', '>=0.10.0', true);
|
||||
testIsValidVersion('1.0.0', '>=0.10.1', true);
|
||||
testIsValidVersion('1.0.0', '>=1.0.0', true);
|
||||
testIsValidVersion('1.0.0', '>=1.1.0', false);
|
||||
testIsValidVersion('1.0.0', '>=1.0.1', false);
|
||||
testIsValidVersion('1.0.0', '>=2.0.0', false);
|
||||
|
||||
testIsValidVersion('1.0.100', 'x.x.x', true);
|
||||
testIsValidVersion('1.0.100', '0.x.x', true);
|
||||
testIsValidVersion('1.0.100', '0.10.0', false);
|
||||
testIsValidVersion('1.0.100', '0.10.2', false);
|
||||
testIsValidVersion('1.0.100', '^0.10.2', true);
|
||||
testIsValidVersion('1.0.100', '0.10.x', true);
|
||||
testIsValidVersion('1.0.100', '^0.10.0', true);
|
||||
testIsValidVersion('1.0.100', '1.0.0', false);
|
||||
testIsValidVersion('1.0.100', '^1.0.0', true);
|
||||
testIsValidVersion('1.0.100', '^1.0.1', true);
|
||||
testIsValidVersion('1.0.100', '^2.0.0', false);
|
||||
testIsValidVersion('1.0.100', '*', true);
|
||||
|
||||
testIsValidVersion('1.100.0', 'x.x.x', true);
|
||||
testIsValidVersion('1.100.0', '0.x.x', true);
|
||||
testIsValidVersion('1.100.0', '0.10.0', false);
|
||||
testIsValidVersion('1.100.0', '0.10.2', false);
|
||||
testIsValidVersion('1.100.0', '^0.10.2', true);
|
||||
testIsValidVersion('1.100.0', '0.10.x', true);
|
||||
testIsValidVersion('1.100.0', '^0.10.0', true);
|
||||
testIsValidVersion('1.100.0', '1.0.0', false);
|
||||
testIsValidVersion('1.100.0', '^1.0.0', true);
|
||||
testIsValidVersion('1.100.0', '^1.1.0', true);
|
||||
testIsValidVersion('1.100.0', '^1.100.0', true);
|
||||
testIsValidVersion('1.100.0', '^2.0.0', false);
|
||||
testIsValidVersion('1.100.0', '*', true);
|
||||
testIsValidVersion('1.100.0', '>=1.99.0', true);
|
||||
testIsValidVersion('1.100.0', '>=1.100.0', true);
|
||||
testIsValidVersion('1.100.0', '>=1.101.0', false);
|
||||
|
||||
testIsValidVersion('2.0.0', 'x.x.x', true);
|
||||
testIsValidVersion('2.0.0', '0.x.x', false);
|
||||
testIsValidVersion('2.0.0', '0.10.0', false);
|
||||
testIsValidVersion('2.0.0', '0.10.2', false);
|
||||
testIsValidVersion('2.0.0', '^0.10.2', false);
|
||||
testIsValidVersion('2.0.0', '0.10.x', false);
|
||||
testIsValidVersion('2.0.0', '^0.10.0', false);
|
||||
testIsValidVersion('2.0.0', '1.0.0', false);
|
||||
testIsValidVersion('2.0.0', '^1.0.0', false);
|
||||
testIsValidVersion('2.0.0', '^1.1.0', false);
|
||||
testIsValidVersion('2.0.0', '^1.100.0', false);
|
||||
testIsValidVersion('2.0.0', '^2.0.0', true);
|
||||
testIsValidVersion('2.0.0', '*', true);
|
||||
});
|
||||
|
||||
test('isValidExtensionVersion', () => {
|
||||
|
||||
function testExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean, expectedResult: boolean): void {
|
||||
let desc: IReducedExtensionDescription = {
|
||||
isBuiltin: isBuiltin,
|
||||
engines: {
|
||||
vscode: desiredVersion
|
||||
},
|
||||
main: hasMain ? 'something' : undefined
|
||||
};
|
||||
let reasons: string[] = [];
|
||||
let actual = isValidExtensionVersion(version, desc, reasons);
|
||||
|
||||
assert.equal(actual, expectedResult, 'version: ' + version + ', desiredVersion: ' + desiredVersion + ', desc: ' + JSON.stringify(desc) + ', reasons: ' + JSON.stringify(reasons));
|
||||
}
|
||||
|
||||
function testIsInvalidExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean): void {
|
||||
testExtensionVersion(version, desiredVersion, isBuiltin, hasMain, false);
|
||||
}
|
||||
|
||||
function testIsValidExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean): void {
|
||||
testExtensionVersion(version, desiredVersion, isBuiltin, hasMain, true);
|
||||
}
|
||||
|
||||
function testIsValidVersion(version: string, desiredVersion: string, expectedResult: boolean): void {
|
||||
testExtensionVersion(version, desiredVersion, false, true, expectedResult);
|
||||
}
|
||||
|
||||
// builtin are allowed to use * or x.x.x
|
||||
testIsValidExtensionVersion('0.10.0-dev', '*', true, true);
|
||||
testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', true, true);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.x.x', true, true);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.10.x', true, true);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.x.x', true, true);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.10.x', true, true);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '*', true, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', true, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.x.x', true, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.10.x', true, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.x.x', true, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.10.x', true, false);
|
||||
|
||||
// normal extensions are allowed to use * or x.x.x only if they have no main
|
||||
testIsInvalidExtensionVersion('0.10.0-dev', '*', false, true);
|
||||
testIsInvalidExtensionVersion('0.10.0-dev', 'x.x.x', false, true);
|
||||
testIsInvalidExtensionVersion('0.10.0-dev', '0.x.x', false, true);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, true);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, true);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, true);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '*', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false);
|
||||
|
||||
// extensions without "main" get no version check
|
||||
testIsValidExtensionVersion('0.10.0-dev', '>=0.9.1-pre.1', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '*', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '*', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false);
|
||||
testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false);
|
||||
testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false);
|
||||
|
||||
// normal extensions with code
|
||||
testIsValidVersion('0.10.0-dev', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.0-dev', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.0-dev', '0.10.0', true);
|
||||
testIsValidVersion('0.10.0-dev', '0.10.2', false);
|
||||
testIsValidVersion('0.10.0-dev', '^0.10.2', false);
|
||||
testIsValidVersion('0.10.0-dev', '0.10.x', true);
|
||||
testIsValidVersion('0.10.0-dev', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.0-dev', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('0.10.0', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.0', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.0', '0.10.0', true);
|
||||
testIsValidVersion('0.10.0', '0.10.2', false);
|
||||
testIsValidVersion('0.10.0', '^0.10.2', false);
|
||||
testIsValidVersion('0.10.0', '0.10.x', true);
|
||||
testIsValidVersion('0.10.0', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.0', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('0.10.1', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.1', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.1', '0.10.0', false);
|
||||
testIsValidVersion('0.10.1', '0.10.2', false);
|
||||
testIsValidVersion('0.10.1', '^0.10.2', false);
|
||||
testIsValidVersion('0.10.1', '0.10.x', true);
|
||||
testIsValidVersion('0.10.1', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.1', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('0.10.100', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.100', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.10.100', '0.10.0', false);
|
||||
testIsValidVersion('0.10.100', '0.10.2', false);
|
||||
testIsValidVersion('0.10.100', '^0.10.2', true);
|
||||
testIsValidVersion('0.10.100', '0.10.x', true);
|
||||
testIsValidVersion('0.10.100', '^0.10.0', true);
|
||||
testIsValidVersion('0.10.100', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('0.11.0', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.11.0', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('0.11.0', '0.10.0', false);
|
||||
testIsValidVersion('0.11.0', '0.10.2', false);
|
||||
testIsValidVersion('0.11.0', '^0.10.2', false);
|
||||
testIsValidVersion('0.11.0', '0.10.x', false);
|
||||
testIsValidVersion('0.11.0', '^0.10.0', false);
|
||||
testIsValidVersion('0.11.0', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('1.0.0', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.0.0', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.0.0', '0.10.0', false);
|
||||
testIsValidVersion('1.0.0', '0.10.2', false);
|
||||
testIsValidVersion('1.0.0', '^0.10.2', true);
|
||||
testIsValidVersion('1.0.0', '0.10.x', true);
|
||||
testIsValidVersion('1.0.0', '^0.10.0', true);
|
||||
testIsValidVersion('1.0.0', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('1.10.0', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.10.0', '1.x.x', true);
|
||||
testIsValidVersion('1.10.0', '1.10.0', true);
|
||||
testIsValidVersion('1.10.0', '1.10.2', false);
|
||||
testIsValidVersion('1.10.0', '^1.10.2', false);
|
||||
testIsValidVersion('1.10.0', '1.10.x', true);
|
||||
testIsValidVersion('1.10.0', '^1.10.0', true);
|
||||
testIsValidVersion('1.10.0', '*', false); // fails due to lack of specificity
|
||||
|
||||
|
||||
// Anything < 1.0.0 is compatible
|
||||
|
||||
testIsValidVersion('1.0.0', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.0.0', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.0.0', '0.10.0', false);
|
||||
testIsValidVersion('1.0.0', '0.10.2', false);
|
||||
testIsValidVersion('1.0.0', '^0.10.2', true);
|
||||
testIsValidVersion('1.0.0', '0.10.x', true);
|
||||
testIsValidVersion('1.0.0', '^0.10.0', true);
|
||||
testIsValidVersion('1.0.0', '1.0.0', true);
|
||||
testIsValidVersion('1.0.0', '^1.0.0', true);
|
||||
testIsValidVersion('1.0.0', '^2.0.0', false);
|
||||
testIsValidVersion('1.0.0', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('1.0.100', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.0.100', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.0.100', '0.10.0', false);
|
||||
testIsValidVersion('1.0.100', '0.10.2', false);
|
||||
testIsValidVersion('1.0.100', '^0.10.2', true);
|
||||
testIsValidVersion('1.0.100', '0.10.x', true);
|
||||
testIsValidVersion('1.0.100', '^0.10.0', true);
|
||||
testIsValidVersion('1.0.100', '1.0.0', false);
|
||||
testIsValidVersion('1.0.100', '^1.0.0', true);
|
||||
testIsValidVersion('1.0.100', '^1.0.1', true);
|
||||
testIsValidVersion('1.0.100', '^2.0.0', false);
|
||||
testIsValidVersion('1.0.100', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('1.100.0', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.100.0', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('1.100.0', '0.10.0', false);
|
||||
testIsValidVersion('1.100.0', '0.10.2', false);
|
||||
testIsValidVersion('1.100.0', '^0.10.2', true);
|
||||
testIsValidVersion('1.100.0', '0.10.x', true);
|
||||
testIsValidVersion('1.100.0', '^0.10.0', true);
|
||||
testIsValidVersion('1.100.0', '1.0.0', false);
|
||||
testIsValidVersion('1.100.0', '^1.0.0', true);
|
||||
testIsValidVersion('1.100.0', '^1.1.0', true);
|
||||
testIsValidVersion('1.100.0', '^1.100.0', true);
|
||||
testIsValidVersion('1.100.0', '^2.0.0', false);
|
||||
testIsValidVersion('1.100.0', '*', false); // fails due to lack of specificity
|
||||
|
||||
testIsValidVersion('2.0.0', 'x.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('2.0.0', '0.x.x', false); // fails due to lack of specificity
|
||||
testIsValidVersion('2.0.0', '0.10.0', false);
|
||||
testIsValidVersion('2.0.0', '0.10.2', false);
|
||||
testIsValidVersion('2.0.0', '^0.10.2', false);
|
||||
testIsValidVersion('2.0.0', '0.10.x', false);
|
||||
testIsValidVersion('2.0.0', '^0.10.0', false);
|
||||
testIsValidVersion('2.0.0', '1.0.0', false);
|
||||
testIsValidVersion('2.0.0', '^1.0.0', false);
|
||||
testIsValidVersion('2.0.0', '^1.1.0', false);
|
||||
testIsValidVersion('2.0.0', '^1.100.0', false);
|
||||
testIsValidVersion('2.0.0', '^2.0.0', true);
|
||||
testIsValidVersion('2.0.0', '*', false); // fails due to lack of specificity
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user