Skip to content

Commit

Permalink
Fix: no-unsupported-features goes wrong on >=7.10.0 (fixes #78)
Browse files Browse the repository at this point in the history
  • Loading branch information
mysticatea committed Jun 1, 2017
1 parent 0e487f9 commit deb4f55
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 174 deletions.
138 changes: 93 additions & 45 deletions lib/rules/no-unsupported-features.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,27 @@ const getValueIfString = require("../util/get-value-if-string")
// Helpers
//------------------------------------------------------------------------------

const VERSIONS = [0.10, 0.12, 4, 5, 6, 7, 7.6, 8]
const VERSION_MAP = new Map([
[0.1, "0.10.0"],
[0.12, "0.12.0"],
[4, "4.0.0"],
[5, "5.0.0"],
[6, "6.0.0"],
[7, "7.0.0"],
[7.6, "7.6.0"],
[8, "8.0.0"],
])
const VERSION_SCHEMA = {
anyOf: [
{enum: Array.from(VERSION_MAP.keys())},
{
type: "string",
pattern: "^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)$",
},
],
}
const DEFAULT_VERSION = "4.0.0"
const MINIMUM_VERSION = "0.0.0"
const OPTIONS = Object.keys(features)
const FUNC_TYPE = /^(?:Arrow)?Function(?:Declaration|Expression)$/
const CLASS_TYPE = /^Class(?:Declaration|Expression)$/
Expand Down Expand Up @@ -65,19 +85,31 @@ const PROPERTY_TEST_TARGETS = {
}

/**
* Gets major version of 'semver.Comparator'.
*
* @param {semver.Comparator} comparator - A comparator to get.
* @returns {number} The major version of the comparator.
* Get the smaller value of the given 2 semvers.
* @param {string|null} a A semver to compare.
* @param {string} b Another semver to compare.
* @returns {string} The smaller value.
*/
function parseVersion(comparator) {
const major = comparator.semver.major
const minor = comparator.semver.minor
function min(a, b) {
return (
a == null ? b :
semver.lt(a, b) ? a :
/* otherwise */ b
)
}

if (major >= 1 || minor >= 10) {
return parseFloat(`${major}.${minor}`)
}
return 0.10
/**
* Get the larger value of the given 2 semvers.
* @param {string|null} a A semver to compare.
* @param {string} b Another semver to compare.
* @returns {string} The larger value.
*/
function max(a, b) {
return (
a == null ? b :
semver.gt(a, b) ? a :
/* otherwise */ b
)
}

/**
Expand All @@ -87,7 +119,7 @@ function parseVersion(comparator) {
* If it's nothing, this returns '4'.
*
* @param {string} filename - The file name of the current linting file.
* @returns {number} The default version configuration.
* @returns {string} The default version configuration.
*/
function getDefaultVersion(filename) {
const info = getPackageJson(filename)
Expand All @@ -96,27 +128,35 @@ function getDefaultVersion(filename) {
try {
const range = new semver.Range(nodeVersion)
const comparators = Array.prototype.concat.apply([], range.set)
const version = comparators.reduce(
(minVersion, comparator) => {
const ret = comparators.reduce(
(lu, comparator) => {
const op = comparator.operator
const v = comparator.semver

if (op === "" || op === ">=") {
lu.lower = min(lu.lower, `${v.major}.${v.minor}.${v.patch}`)
}
else if (op === ">") {
lu.lower = min(lu.lower, `${v.major}.${v.minor}.${v.patch + 1}`)
}

if (op === "" || op === ">" || op === ">=") {
return Math.min(minVersion, parseVersion(comparator))
if (op === "" || op === "<=" || op === "<") {
lu.upper = max(lu.upper, `${v.major}.${v.minor}.${v.patch}`)
}
return minVersion

return lu
},
Number.POSITIVE_INFINITY
{lower: null, upper: null}
)

if (Number.isFinite(version)) {
return version
if (ret.lower == null && ret.upper != null) {
return MINIMUM_VERSION
}
return ret.lower || DEFAULT_VERSION
}
catch (_err) {
// ignore
return DEFAULT_VERSION
}

return 4
}

/**
Expand Down Expand Up @@ -154,29 +194,29 @@ function isIgnored(key, ignores) {
/**
* Parses the options.
*
* @param {object} options - An option object to parse.
* @param {number|string|object|undefined} options - An option object to parse.
* @param {number} defaultVersion - The default version to use if the version option was omitted.
* @returns {object} Parsed value.
*/
function parseOptions(options, defaultVersion) {
let version = 0
let ignores = null
let version = defaultVersion
let ignores = []

if (typeof options === "number") {
version = options || defaultVersion
ignores = []
version = VERSION_MAP.get(options)
}
else if (typeof options === "string") {
version = options
}
else if (typeof options === "object") {
version = options.version || defaultVersion
version = (typeof options.version === "number")
? VERSION_MAP.get(options.version)
: options.version || defaultVersion
ignores = options.ignores || []
}
else {
version = defaultVersion
ignores = []
}

return Object.freeze({
version: version < 1 ? version.toFixed(2) : String(version),
version,
features: Object.freeze(OPTIONS.reduce(
(retv, key) => {
const feature = features[key]
Expand All @@ -189,20 +229,26 @@ function parseOptions(options, defaultVersion) {
supportedInStrict: true,
})
}
else if (typeof feature.node === "number") {
else if (typeof feature.node === "string") {
retv[key] = Object.freeze({
name: feature.name,
singular: Boolean(feature.singular),
supported: version >= feature.node,
supportedInStrict: version >= feature.node,
supported: semver.gte(version, feature.node),
supportedInStrict: semver.gte(version, feature.node),
})
}
else {
retv[key] = Object.freeze({
name: feature.name,
singular: Boolean(feature.singular),
supported: version >= feature.node.sloppy,
supportedInStrict: version >= feature.node.strict,
supported:
feature.node != null &&
feature.node.sloppy != null &&
semver.gte(version, feature.node.sloppy),
supportedInStrict:
feature.node != null &&
feature.node.strict != null &&
semver.gte(version, feature.node.strict),
})
}

Expand Down Expand Up @@ -363,7 +409,7 @@ function create(context) {
if (!feature.supportedInStrict) {
context.report({
node,
message: "{{feature}} {{be}} not supported yet on Node v{{version}}.",
message: "{{feature}} {{be}} not supported yet on Node {{version}}.",
data: {
feature: feature.name,
be: feature.singular ? "is" : "are",
Expand All @@ -374,7 +420,7 @@ function create(context) {
else if (!isStrict()) {
context.report({
node,
message: "{{feature}} {{be}} not supported yet on Node v{{version}}.",
message: "{{feature}} {{be}} not supported yet on Node {{version}}.",
data: {
feature: `${feature.name} in non-strict mode`,
be: feature.singular ? "is" : "are",
Expand All @@ -389,6 +435,7 @@ function create(context) {
// Program
//----------------------------------------------------------------------

//eslint-disable-next-line complexity
"Program:exit"() {
// Check new global variables.
for (const name of NEW_BUILTIN_TYPES) {
Expand Down Expand Up @@ -683,12 +730,13 @@ module.exports = {
fixable: false,
schema: [
{
oneOf: [
{enum: VERSIONS},
anyOf: [
VERSION_SCHEMA.anyOf[0],
VERSION_SCHEMA.anyOf[1],
{
type: "object",
properties: {
version: {enum: VERSIONS},
version: VERSION_SCHEMA,
ignores: {
type: "array",
items: {enum: getIgnoresEnum()},
Expand Down
Loading

0 comments on commit deb4f55

Please sign in to comment.