src/vs/platform/extensions/common/extensionValidator.ts/validateExtensionManifest
export function validateExtensionManifest(productVersion: string, productDate: ProductDate, extensionLocation: URI, extensionManifest: IExtensionManifest, extensionIsBuiltin: boolean): readonly [Severity, string][] {
	const validations: [Severity, string][] = [];
	if (typeof extensionManifest.publisher !== 'undefined' && typeof extensionManifest.publisher !== 'string') {
		validations.push([Severity.Error, nls.localize('extensionDescription.publisher', "property publisher must be of type `string`.")]);
		return validations;
	}
	if (typeof extensionManifest.name !== 'string') {
		validations.push([Severity.Error, nls.localize('extensionDescription.name', "property `{0}` is mandatory and must be of type `string`", 'name')]);
		return validations;
	}
	if (typeof extensionManifest.version !== 'string') {
		validations.push([Severity.Error, nls.localize('extensionDescription.version', "property `{0}` is mandatory and must be of type `string`", 'version')]);
		return validations;
	}
	if (!extensionManifest.engines) {
		validations.push([Severity.Error, nls.localize('extensionDescription.engines', "property `{0}` is mandatory and must be of type `object`", 'engines')]);
		return validations;
	}
	if (typeof extensionManifest.engines.vscode !== 'string') {
		validations.push([Severity.Error, nls.localize('extensionDescription.engines.vscode', "property `{0}` is mandatory and must be of type `string`", 'engines.vscode')]);
		return validations;
	}
	if (typeof extensionManifest.extensionDependencies !== 'undefined') {
		if (!isStringArray(extensionManifest.extensionDependencies)) {
			validations.push([Severity.Error, nls.localize('extensionDescription.extensionDependencies', "property `{0}` can be omitted or must be of type `string[]`", 'extensionDependencies')]);
			return validations;
		}
	}
	if (typeof extensionManifest.activationEvents !== 'undefined') {
		if (!isStringArray(extensionManifest.activationEvents)) {
			validations.push([Severity.Error, nls.localize('extensionDescription.activationEvents1', "property `{0}` can be omitted or must be of type `string[]`", 'activationEvents')]);
			return validations;
		}
		if (typeof extensionManifest.main === 'undefined' && typeof extensionManifest.browser === 'undefined') {
			validations.push([Severity.Error, nls.localize('extensionDescription.activationEvents2', "properties `{0}` and `{1}` must both be specified or must both be omitted", 'activationEvents', 'main')]);
			return validations;
		}
	}
	if (typeof extensionManifest.extensionKind !== 'undefined') {
		if (typeof extensionManifest.main === 'undefined') {
			validations.push([Severity.Warning, nls.localize('extensionDescription.extensionKind', "property `{0}` can be defined only if property `main` is also defined.", 'extensionKind')]);
			// not a failure case
		}
	}
	if (typeof extensionManifest.main !== 'undefined') {
		if (typeof extensionManifest.main !== 'string') {
			validations.push([Severity.Error, nls.localize('extensionDescription.main1', "property `{0}` can be omitted or must be of type `string`", 'main')]);
			return validations;
		} else {
			const mainLocation = joinPath(extensionLocation, extensionManifest.main);
			if (!isEqualOrParent(mainLocation, extensionLocation)) {
				validations.push([Severity.Warning, nls.localize('extensionDescription.main2', "Expected `main` ({0}) to be included inside extension's folder ({1}). This might make the extension non-portable.", mainLocation.path, extensionLocation.path)]);
				// not a failure case
			}
		}
		if (typeof extensionManifest.activationEvents === 'undefined') {
			validations.push([Severity.Error, nls.localize('extensionDescription.main3', "properties `{0}` and `{1}` must both be specified or must both be omitted", 'activationEvents', 'main')]);
			return validations;
		}
	}
	if (typeof extensionManifest.browser !== 'undefined') {
		if (typeof extensionManifest.browser !== 'string') {
			validations.push([Severity.Error, nls.localize('extensionDescription.browser1', "property `{0}` can be omitted or must be of type `string`", 'browser')]);
			return validations;
		} else {
			const browserLocation = joinPath(extensionLocation, extensionManifest.browser);
			if (!isEqualOrParent(browserLocation, extensionLocation)) {
				validations.push([Severity.Warning, nls.localize('extensionDescription.browser2', "Expected `browser` ({0}) to be included inside extension's folder ({1}). This might make the extension non-portable.", browserLocation.path, extensionLocation.path)]);
				// not a failure case
			}
		}
		if (typeof extensionManifest.activationEvents === 'undefined') {
			validations.push([Severity.Error, nls.localize('extensionDescription.browser3', "properties `{0}` and `{1}` must both be specified or must both be omitted", 'activationEvents', 'browser')]);
			return validations;
		}
	}

	if (!semver.valid(extensionManifest.version)) {
		validations.push([Severity.Error, nls.localize('notSemver', "Extension version is not semver compatible.")]);
		return validations;
	}

	const notices: string[] = [];
	const isValid = isValidExtensionVersion(productVersion, productDate, extensionManifest, extensionIsBuiltin, notices);
	if (!isValid) {
		for (const notice of notices) {
			validations.push([Severity.Error, notice]);
		}
	}
	return validations;
}