dmclc
Version:
Dolphin Minecraft Launcher Core
189 lines (188 loc) • 6.89 kB
JavaScript
/*
* Ported from Fabric Loader.
* Copyright 2016 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import assert from "assert";
import { SemanticVersion } from "./SemanticVersion.js";
import { SemanticVersionImpl } from "./SemanticVersionImpl.js";
import { VersionComparisonOperator } from "./VersionComparisonOperator.js";
import { VersionIntervalImpl } from "./VersionIntervalImpl.js";
import { VersionParser } from "./VersionParser.js";
import { VersionParsingException } from "./VersionParsingException.js";
import { VersionPredicate } from "./VersionPredicate.js";
class VersionPredicateParser {
static OPERATORS = VersionComparisonOperator.values;
static parseOne(predicate) {
const predicateList = [];
for (let s of predicate.split(" ")) {
s = s.trim();
if (s === "" || s === "*") {
continue;
}
let operator = VersionComparisonOperator.EQUAL;
for (const op of VersionPredicateParser.OPERATORS) {
if (s.startsWith(op.getSerialized())) {
operator = op;
s = s.substring(op.getSerialized().length);
break;
}
}
let version = VersionParser.parse(s, true);
if (version instanceof SemanticVersion) {
if (version.hasWildcard()) { // .x version -> replace with conventional version by replacing the operator
if (operator != VersionComparisonOperator.EQUAL) {
throw new VersionParsingException("Invalid predicate: " + predicate + ", version ranges with wildcards (.X) require using the equality operator or no operator at all!");
}
assert(!version.getPrereleaseKey());
const compCount = version.getVersionComponentCount();
assert(compCount == 2 || compCount == 3);
operator = compCount == 2 ? VersionComparisonOperator.SAME_TO_NEXT_MAJOR : VersionComparisonOperator.SAME_TO_NEXT_MINOR;
const newComponents = new Array(version.getVersionComponentCount() - 1);
for (let i = 0; i < version.getVersionComponentCount() - 1; i++) {
newComponents[i] = version.getVersionComponent(i);
}
version = new SemanticVersionImpl(newComponents, "", version.getBuildKey());
}
}
else if (!operator.isMinInclusive() && !operator.isMaxInclusive()) { // non-semver without inclusive bound
throw new VersionParsingException("Invalid predicate: " + predicate + ", version ranges need to be semantic version compatible to use operators that exclude the bound!");
}
else { // non-semver with inclusive bound
operator = VersionComparisonOperator.EQUAL;
}
predicateList.push(new SingleVersionPredicate(operator, version));
}
if (predicateList.length === 0) {
return AnyVersionPredicate.INSTANCE;
}
else if (predicateList.length == 1) {
return predicateList[0];
}
else {
return new MultiVersionPredicate(predicateList);
}
}
static parse(predicates) {
const ret = new Set();
for (const version of predicates) {
ret.add(VersionPredicateParser.parseOne(version));
}
return ret;
}
static getAny() {
return AnyVersionPredicate.INSTANCE;
}
}
export { VersionPredicateParser };
class AnyVersionPredicate extends VersionPredicate {
static INSTANCE = new AnyVersionPredicate();
constructor() {
super();
}
test() {
return true;
}
getTerms() {
return [];
}
getInterval() {
return VersionIntervalImpl.INFINITE;
}
toString() {
return "*";
}
}
class SingleVersionPredicate {
operator;
refVersion;
constructor(operator, refVersion) {
this.operator = operator;
this.refVersion = refVersion;
}
test(version) {
return this.operator.test(version, this.refVersion);
}
getTerms() {
return [this];
}
getInterval() {
if (this.refVersion instanceof SemanticVersion) {
return new VersionIntervalImpl(this.operator.minVersion(this.refVersion), this.operator.isMinInclusive(), this.operator.maxVersion(this.refVersion), this.operator.isMaxInclusive());
}
else {
return new VersionIntervalImpl(this.refVersion, true, this.refVersion, true);
}
}
getOperator() {
return this.operator;
}
getReferenceVersion() {
return this.refVersion;
}
equals(obj) {
if (obj instanceof SingleVersionPredicate) {
return this.operator == obj.operator && this.refVersion.equals(obj.refVersion);
}
else {
return false;
}
}
toString() {
return this.operator.getSerialized().concat(this.refVersion.toString());
}
}
class MultiVersionPredicate extends VersionPredicate {
predicates;
constructor(predicates) {
super();
this.predicates = predicates;
}
test(version) {
for (const predicate of this.predicates) {
if (!predicate.test(version))
return false;
}
return true;
}
getTerms() {
return this.predicates;
}
getInterval() {
if (this.predicates.length === 0)
return AnyVersionPredicate.INSTANCE.getInterval();
let ret = this.predicates[0].getInterval();
for (let i = 1; i < this.predicates.length; i++) {
ret = VersionIntervalImpl.andOne(ret, this.predicates[i].getInterval());
}
return ret;
}
equals(obj) {
if (obj instanceof MultiVersionPredicate) {
return !this.predicates.map((v, i) => obj.predicates[i].equals(v)).includes(false);
}
else {
return false;
}
}
toString() {
const ret = [];
for (const predicate of this.predicates) {
if (ret.length > 0)
ret.push(" ");
ret.push(predicate.toString());
}
return ret.join("");
}
}