Skip to content

Commit

Permalink
use ast-metadata-inferer (#175)
Browse files Browse the repository at this point in the history
* v2.7.0

* initial working commit

* testing improvements, bump ast-metadata-inferer

* add failing test case

* update readme and changelog

* handle case when versionAdded === null

* bump ast-metadata-inferer
  • Loading branch information
amilajack committed Feb 28, 2019
1 parent 782fc62 commit 02416ee
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 72 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,7 @@
## v3.0.0
### Added
- Support for ~4000 JS API's using [ast-metadata-inferer](https://github.com/amilajack/ast-metadata-inferer)

## v2.7.0
### Added
- `Object.values()` support
Expand Down
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -97,3 +97,8 @@ This project was inspired by a two hour conversation I had with someone on the e

## Demo
For a minimal demo, see [amilajack/eslint-plugin-compat-demo](https://github.com/amilajack/eslint-plugin-compat-demo)

## Related

* [ast-metadata-inferer](https://github.com/amilajack/ast-metadata-inferer)
* [compat-db](https://github.com/amilajack/compat-db)
8 changes: 5 additions & 3 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-compat",
"version": "2.6.3",
"version": "3.0.0-0",
"description": "Lint browser compatibility of API used",
"main": "lib/index.js",
"repository": {
Expand All @@ -26,7 +26,7 @@
],
"homepage": "https://github.com/amilajack/eslint-plugin-compat#readme",
"scripts": {
"build": "cross-env NODE_ENV=production rm -rf lib && babel src --out-dir lib",
"build": "cross-env NODE_ENV=production rm -rf lib && babel src --out-dir lib --source-maps inline",
"flow": "flow",
"flow-typed": "flow-typed install --ignoreDeps peer dev",
"lint": "eslint --cache --format=node_modules/eslint-formatter-pretty .",
Expand Down Expand Up @@ -59,9 +59,11 @@
},
"dependencies": {
"@babel/runtime": "^7.3.1",
"ast-metadata-inferer": "^0.1.1-3",
"browserslist": "^4.4.1",
"caniuse-db": "^1.0.30000935",
"mdn-browser-compat-data": "^0.0.68"
"mdn-browser-compat-data": "^0.0.68",
"semver": "^5.6.0"
},
"peerDependencies": {
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0"
Expand Down
8 changes: 4 additions & 4 deletions src/Lint.js
@@ -1,5 +1,5 @@
// @flow
import { rules } from './providers/index';
import { rules } from './providers';
import type { Node, ESLintNode, Targets, isValidObject } from './LintTypes';

export function generateErrorName(_node: Node): string {
Expand All @@ -17,13 +17,13 @@ export function generateErrorName(_node: Node): string {
export default function Lint(
eslintNode: ESLintNode,
targets: Targets = ['chrome', 'firefox', 'safari', 'edge'],
polyfills: Set<string> = new Set()
polyfills: Set<string>
): isValidObject {
// Find the corresponding rules for a eslintNode by it's ASTNodeType
// Find the corresponding rules for a eslintNode by it's astNodeType
const failingRule = rules
.filter(
(rule: Node): boolean =>
rule.ASTNodeType === eslintNode.type &&
rule.astNodeType === eslintNode.type &&
// Check if polyfill is provided
!polyfills.has(rule.id)
)
Expand Down
8 changes: 5 additions & 3 deletions src/LintTypes.js
@@ -1,7 +1,9 @@
// @flow
export type node = {
type?: string,
name?: string
type?: 'MemberExpression' | 'NewExpression' | 'CallExpression',
name?: string,
object: string,
property: string | void
};

export type Target = {
Expand All @@ -24,7 +26,7 @@ export type ESLintNode = {
} & node;

export type Node = {
ASTNodeType: string,
astNodeType: string,
id: string,
object: string,
property?: string,
Expand Down
2 changes: 1 addition & 1 deletion src/Versioning.js
@@ -1,5 +1,5 @@
// @flow
import browserslist from 'browserslist'; // eslint-disable-line
import browserslist from 'browserslist';
import type { BrowserListConfig } from './rules/compat';

type TargetListItem = {
Expand Down
63 changes: 23 additions & 40 deletions src/providers/CanIUseProvider.js
@@ -1,6 +1,6 @@
// @flow
// $FlowFixMe: Flow import error
import caniuseRecord from 'caniuse-db/fulldata-json/data-2.0.json'; // eslint-disable-line
import caniuseRecords from 'caniuse-db/fulldata-json/data-2.0.json';
import type { Node, ESLintNode, Targets, Target } from '../LintTypes';

type TargetMetadata = {
Expand All @@ -14,7 +14,7 @@ type CanIUseStats = {
}
};

type CanIUseRecord = {
type CanIUseRecords = {
data: CanIUseStats
};

Expand Down Expand Up @@ -71,7 +71,7 @@ function formatTargetNames(target: Target): string {
}

/**
* Check version for the range format.
* Check if a browser version is in the range format
* ex. 10.0-10.2
*/
function versionIsRange(version: string): boolean {
Expand All @@ -88,10 +88,11 @@ function compareRanges(targetVersion: number, statsVersion: string): boolean {
/*
* Check the CanIUse database to see if targets are supported
*/
function canIUseSupported(
stats: CanIUseStats,
function canIUseIsNotSupported(
node: Node,
{ version, target, parsedVersion }: Target
): boolean {
const { stats } = (caniuseRecords: CanIUseRecords).data[node.id];
const targetStats = stats[target];
return versionIsRange(version)
? Object.keys(targetStats).some(
Expand All @@ -111,9 +112,8 @@ export function getUnsupportedTargets(
node: Node,
targets: Targets
): Array<string> {
const { stats } = (caniuseRecord: CanIUseRecord).data[node.id];
return targets
.filter(target => canIUseSupported(stats, target))
.filter(target => canIUseIsNotSupported(node, target))
.map(formatTargetNames);
}

Expand Down Expand Up @@ -146,119 +146,102 @@ function isValid(
return true;
}

return getUnsupportedTargets(node, targets).length === 0;
return !getUnsupportedTargets(node, targets).length;
}

//
// TODO: Migrate to compat-db
// TODO: Refactor isValid(), remove from rules
//

const CanIUseProvider: Array<Node> = [
// new ServiceWorker()
{
id: 'serviceworkers',
ASTNodeType: 'NewExpression',
astNodeType: 'NewExpression',
object: 'ServiceWorker'
},
{
id: 'serviceworkers',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'navigator',
property: 'serviceWorker'
},
// document.querySelector()
{
id: 'queryselector',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'document',
property: 'querySelector'
},
// WebAssembly
{
id: 'wasm',
ASTNodeType: 'MemberExpression',
object: 'WebAssembly'
},
// IntersectionObserver
{
id: 'intersectionobserver',
ASTNodeType: 'NewExpression',
astNodeType: 'NewExpression',
object: 'IntersectionObserver'
},
// PaymentRequest
{
id: 'payment-request',
ASTNodeType: 'NewExpression',
astNodeType: 'NewExpression',
object: 'PaymentRequest'
},
// Promises
{
id: 'promises',
ASTNodeType: 'NewExpression',
astNodeType: 'NewExpression',
object: 'Promise'
},
{
id: 'promises',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'Promise',
property: 'resolve'
},
{
id: 'promises',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'Promise',
property: 'all'
},
{
id: 'promises',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'Promise',
property: 'race'
},
{
id: 'promises',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'Promise',
property: 'reject'
},
// fetch
{
id: 'fetch',
ASTNodeType: 'CallExpression',
astNodeType: 'CallExpression',
object: 'fetch'
},
// document.currentScript()
{
id: 'document-currentscript',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'document',
property: 'currentScript'
},
// URL
{
id: 'url',
ASTNodeType: 'NewExpression',
astNodeType: 'NewExpression',
object: 'URL'
},
// URLSearchParams
{
id: 'urlsearchparams',
ASTNodeType: 'NewExpression',
astNodeType: 'NewExpression',
object: 'URLSearchParams'
},
// performance.now()
{
id: 'high-resolution-time',
ASTNodeType: 'MemberExpression',
astNodeType: 'MemberExpression',
object: 'performance',
property: 'now'
},
{
id: 'object-values',
ASTNodeType: 'MemberExpression',
object: 'Object',
property: 'values'
}
].map(rule =>
Object.assign({}, rule, {
Expand Down

0 comments on commit 02416ee

Please sign in to comment.