Skip to content

Commit

Permalink
Reconfigure webpack to export javascript rule files separately
Browse files Browse the repository at this point in the history
  • Loading branch information
willdurand committed Jun 10, 2020
1 parent 01c452b commit ea40fee
Show file tree
Hide file tree
Showing 23 changed files with 141 additions and 116 deletions.
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
!README.md
!bin/addons-linter
!dist/addons-linter.*
!dist/locale/**
!dist/locale/**
!dist/rules/**
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ node_js:
- 'v10.21.0'
- 'v12.18.0'
script:
- npm run test-ci
- node scripts/build-locales
- npm run build
- npm run test-ci
- npm run lint
# run integration tests using an addons-linter binary in a production-like environment
- npm run test-integration:production
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ If you have Node.js installed, here's the quick start to getting your developmen
git clone https://github.com/mozilla/addons-linter.git
cd addons-linter
npm install
# Build the project.
npm run build
# Run the test-suite and watch for changes. Use `npm run test-once` to
# just run it once.
npm run test
Expand Down Expand Up @@ -156,7 +158,7 @@ Dependencies are automatically kept up-to-date using [renovatebot](https://renov

### Building

You can run `npm build` to build the library.
You can run `npm run build` to build the library.

Once you build the library you can use the CLI in `bin/addons-linter`.

Expand Down
32 changes: 30 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ export function createInstance({
return new Linter(config);
}

export default Linter;
export default {
Linter,
createInstance,
isRunFromCLI,
};
2 changes: 1 addition & 1 deletion src/rules/javascript/content-scripts-file-absent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
CONTENT_SCRIPT_EMPTY,
} from 'messages/javascript';

module.exports = {
export default {
create(context) {
const existingFiles = Object.keys(context.settings.existingFiles || {}).map(
(fileName) => {
Expand Down
4 changes: 1 addition & 3 deletions src/rules/javascript/deprecated-entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ export const DEPRECATED_ENTITIES = [
},
];

module.exports = {
DEPRECATED_ENTITIES,

export default {
create(context) {
return {
// eslint-disable-next-line consistent-return
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/event-listener-fourth.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EVENT_LISTENER_FOURTH } from 'messages/javascript';
import { getNodeReference } from 'utils';

module.exports = {
export default {
create(context) {
return {
// eslint-disable-next-line consistent-return
Expand Down
5 changes: 2 additions & 3 deletions src/rules/javascript/global-require-arg.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import { UNEXPECTED_GLOGAL_ARG } from 'messages';
import { getVariable } from 'utils';

/*
* This rule will detect a global passed to `require()` as the first arg
*
* This rule will detect a global passed to `require()` as the first argument.
*/
module.exports = {
export default {
create(context) {
return {
// eslint-disable-next-line consistent-return
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/opendialog-nonlit-uri.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { OPENDIALOG_NONLIT_URI } from 'messages';

module.exports = {
export default {
create(context) {
return {
// eslint-disable-next-line consistent-return
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/opendialog-remote-uri.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isLocalUrl } from 'utils';
import { OPENDIALOG_REMOTE_URI } from 'messages';

module.exports = {
export default {
create(context) {
return {
// eslint-disable-next-line consistent-return
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/webextension-api-compat-android.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ANDROID_INCOMPATIBLE_API } from 'messages/javascript';
import { createCompatibilityRule } from 'utils';
import { hasBrowserApi } from 'schema/browser-apis';

module.exports = {
export default {
create(context) {
return createCompatibilityRule(
'firefox_android',
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/webextension-api-compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { INCOMPATIBLE_API } from 'messages/javascript';
import { createCompatibilityRule } from 'utils';
import { hasBrowserApi } from 'schema/browser-apis';

module.exports = {
export default {
create(context) {
return createCompatibilityRule(
'firefox',
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/webextension-api.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isTemporaryApi } from 'schema/browser-apis';
import { apiToMessage, isBrowserNamespace } from 'utils';

module.exports = {
export default {
create(context) {
return {
// eslint-disable-next-line consistent-return
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/webextension-deprecated-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DEPRECATED_JAVASCRIPT_APIS } from 'const';
import { isDeprecatedApi, hasBrowserApi } from 'schema/browser-apis';
import { isBrowserNamespace } from 'utils';

module.exports = {
export default {
create(context) {
return {
MemberExpression(node) {
Expand Down
2 changes: 1 addition & 1 deletion src/rules/javascript/webextension-unsupported-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { UNSUPPORTED_API } from 'messages/javascript';
import { hasBrowserApi } from 'schema/browser-apis';
import { isBrowserNamespace } from 'utils';

module.exports = {
export default {
create(context) {
return {
MemberExpression(node) {
Expand Down
20 changes: 15 additions & 5 deletions src/scanners/javascript.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* global appRoot */
import path from 'path';

import ESLint from 'eslint';
Expand Down Expand Up @@ -39,10 +40,15 @@ export default class JavaScriptScanner {
return 'javascript';
}

async scan(
async scan({
_ESLint = ESLint,
{ _ruleMapping = ESLINT_RULE_MAPPING, _messages = messages } = {}
) {
_messages = messages,
_ruleMapping = ESLINT_RULE_MAPPING,
// This tells ESLint where to expect the ESLint rules for addons-linter.
// Its default value is defined below. This property is mainly used for
// testing purposes.
_rulePaths = undefined,
} = {}) {
this.sourceType = this.detectSourceType(this.filename);

const rules = {};
Expand All @@ -64,7 +70,11 @@ export default class JavaScriptScanner {
sourceType: this.sourceType,
},
rules,
rulePaths: [path.join(__dirname, '..', 'rules', 'javascript')],
// The default value for `rulePaths` is configured so that it finds the
// files exported by webpack when this project is built.
rulePaths: _rulePaths || [
path.join(appRoot, 'dist', 'rules', 'javascript'),
],
plugins: ['no-unsanitized'],
allowInlineConfig: false,

Expand Down Expand Up @@ -104,7 +114,7 @@ export default class JavaScriptScanner {
if (typeof message.message === 'undefined') {
throw new Error(
oneLine`JS rules must pass a valid message as
the second argument to context.report()`
the second argument to context.report()`
);
}

Expand Down
9 changes: 9 additions & 0 deletions tests/fixtures/rules/javascript/message-rule/message-rule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
create: (context) => {
return {
MemberExpression(node) {
context.report(node, 'this is the message');
},
};
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
create: (context) => {
return {
Identifier: (node) => {
const metadata = context.settings.addonMetadata;

if (typeof metadata !== 'object') {
context.report(node, 'Metadata should be an object.');
}

if (metadata.guid !== 'snowflake') {
context.report(node, 'Metadata properties not present.');
}
}
}
}
};
9 changes: 9 additions & 0 deletions tests/setup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import fs from 'fs';
import path from 'path';

import sinon from 'sinon';

// Setup sinon global to be a sandbox which is restored
Expand All @@ -22,6 +25,12 @@ jest.mock('cli', () => {
};
});

global.appRoot = path.join(__dirname, '..');

if (!fs.existsSync(path.join(global.appRoot, 'dist'))) {
throw new Error('Please run `npm run build` before running the test suite.');
}

afterEach(() => {
global.sinon.restore();
});
19 changes: 13 additions & 6 deletions tests/unit/helpers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import path from 'path';
import fs from 'fs';
import { Readable, Stream } from 'stream';
import { assert } from 'assert';
Expand Down Expand Up @@ -240,17 +241,17 @@ export function getStreamableIO(files) {
getFiles: () => {
return Promise.resolve(files);
},
getFileAsStream: (path) => {
getFileAsStream: (_path) => {
if (
files[path] instanceof Stream &&
typeof files[path]._read === 'function' &&
typeof files[path]._readableState === 'object'
files[_path] instanceof Stream &&
typeof files[_path]._read === 'function' &&
typeof files[_path]._readableState === 'object'
) {
return Promise.resolve(files[path]);
return Promise.resolve(files[_path]);
}

const stream = new Readable();
stream.push(files[path]);
stream.push(files[_path]);
stream.push(null);
return Promise.resolve(stream);
},
Expand Down Expand Up @@ -381,3 +382,9 @@ export function replacePlaceholders(text, data) {
}
);
}

export const FIXTURES_DIR = path.join(__dirname, '..', 'fixtures');

export const getJsRulePathForRule = (ruleName) => {
return path.join(FIXTURES_DIR, 'rules', 'javascript', ruleName);
};
Loading

0 comments on commit ea40fee

Please sign in to comment.