Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build: add type check using typescript --checkJs #2267

Merged
merged 2 commits into from May 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc
Expand Up @@ -168,6 +168,6 @@
"no-plusplus": 0,
"no-prototype-builtins": 2,
"prefer-template": 2,
"template-curly-spacing": [2, "never"],
"template-curly-spacing": [2, "never"]
}
}
2 changes: 1 addition & 1 deletion lib/rules/destructuring-assignment.js
Expand Up @@ -127,7 +127,7 @@ module.exports = {
handleSFCUsage(node);
}
if (classComponent) {
handleClassUsage(node, classComponent);
handleClassUsage(node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a harmless extra arg being passed - good to clean up. semver-patch.

}
},

Expand Down
3 changes: 2 additions & 1 deletion lib/rules/jsx-closing-bracket-location.js
Expand Up @@ -153,10 +153,11 @@ module.exports = {
* Get the characters used for indentation on the line to be matched
* @param {Object} tokens Locations of the opening bracket, closing bracket and last prop
* @param {String} expectedLocation Expected location for the closing bracket
* @param {Number} correctColumn Expected column for the closing bracket
* @param {Number} [correctColumn] Expected column for the closing bracket. Default to 0
* @return {String} The characters used for indentation
*/
function getIndentation(tokens, expectedLocation, correctColumn) {
correctColumn = correctColumn || 0;
let indentation, spaces = [];
switch (expectedLocation) {
case 'props-aligned':
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/jsx-curly-brace-presence.js
Expand Up @@ -110,7 +110,7 @@ module.exports = {

/**
* Report and fix an unnecessary curly brace violation on a node
* @param {ASTNode} node - The AST node with an unnecessary JSX expression
* @param {ASTNode} JSXExpressionNode - The AST node with an unnecessary JSX expression
*/
function reportUnnecessaryCurly(JSXExpressionNode) {
context.report({
Expand Down
6 changes: 4 additions & 2 deletions lib/rules/jsx-curly-spacing.js
Expand Up @@ -156,8 +156,8 @@ module.exports = {
/**
* Trims text of whitespace between two ranges
* @param {Fixer} fixer - the eslint fixer object
* @param {Location} fromLoc - the start location
* @param {Location} toLoc - the end location
* @param {number} fromLoc - the start location
* @param {number} toLoc - the end location
* @param {string} mode - either 'start' or 'end'
* @param {string=} spacing - a spacing value that will optionally add a space to the removed text
* @returns {Object|*|{range, text}}
Expand All @@ -183,6 +183,7 @@ module.exports = {
* Reports that there shouldn't be a newline after the first token
* @param {ASTNode} node - The node to report in the event of an error.
* @param {Token} token - The token to use for the report.
* @param {string} spacing
* @returns {void}
*/
function reportNoBeginningNewline(node, token, spacing) {
Expand All @@ -201,6 +202,7 @@ module.exports = {
* Reports that there shouldn't be a newline before the last token
* @param {ASTNode} node - The node to report in the event of an error.
* @param {Token} token - The token to use for the report.
* @param {string} spacing
* @returns {void}
*/
function reportNoEndingNewline(node, token, spacing) {
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/jsx-indent-props.js
Expand Up @@ -59,6 +59,7 @@ module.exports = {

const extraColumnStart = 0;
let indentType = 'space';
/** @type {number|'first'} */
let indentSize = 4;

const sourceCode = context.getSourceCode();
Expand Down Expand Up @@ -126,7 +127,6 @@ module.exports = {
* Check indent for nodes list
* @param {ASTNode[]} nodes list of node objects
* @param {Number} indent needed indent
* @param {Boolean} excludeCommas skip comma on start of line
*/
function checkNodesIndent(nodes, indent) {
nodes.forEach(node => {
Expand Down
8 changes: 4 additions & 4 deletions lib/rules/jsx-indent.js
Expand Up @@ -110,7 +110,7 @@ module.exports = {
* @param {ASTNode} node Node violating the indent rule
* @param {Number} needed Expected indentation character count
* @param {Number} gotten Indentation character count in the actual node/code
* @param {Object} loc Error line and column location
* @param {Object} [loc] Error line and column location
*/
function report(node, needed, gotten, loc) {
const msgContext = {
Expand Down Expand Up @@ -141,8 +141,8 @@ module.exports = {
/**
* Get node indent
* @param {ASTNode} node Node to examine
* @param {Boolean} byLastLine get indent of node's last line
* @param {Boolean} excludeCommas skip comma on start of line
* @param {Boolean} [byLastLine] get indent of node's last line
* @param {Boolean} [excludeCommas] skip comma on start of line
* @return {Number} Indent
*/
function getNodeIndent(node, byLastLine, excludeCommas) {
Expand Down Expand Up @@ -204,7 +204,7 @@ module.exports = {
* Check indent for nodes list
* @param {ASTNode} node The node to check
* @param {Number} indent needed indent
* @param {Boolean} excludeCommas skip comma on start of line
* @param {Boolean} [excludeCommas] skip comma on start of line
*/
function checkNodesIndent(node, indent, excludeCommas) {
const nodeIndent = getNodeIndent(node, false, excludeCommas);
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/jsx-sort-props.js
Expand Up @@ -75,7 +75,7 @@ function contextCompare(a, b, options) {
* Create an array of arrays where each subarray is composed of attributes
* that are considered sortable.
* @param {Array<JSXSpreadAttribute|JSXAttribute>} attributes
* @return {Array<Array<JSXAttribute>}
* @return {Array<Array<JSXAttribute>>}
*/
function getGroupsOfSortableAttributes(attributes) {
const sortableAttributeGroups = [];
Expand Down Expand Up @@ -156,7 +156,7 @@ const generateFixerFunction = (node, context, reservedList) => {
* Checks if the `reservedFirst` option is valid
* @param {Object} context The context of the rule
* @param {Boolean|Array<String>} reservedFirst The `reservedFirst` option
* @return {?Function} If an error is detected, a function to generate the error message, otherwise, `undefined`
* @return {Function|undefined} If an error is detected, a function to generate the error message, otherwise, `undefined`
*/
// eslint-disable-next-line consistent-return
function validateReservedFirstConfig(context, reservedFirst) {
Expand Down
1 change: 1 addition & 0 deletions lib/rules/no-danger-with-children.js
Expand Up @@ -28,6 +28,7 @@ module.exports = {
* Takes a ObjectExpression and returns the value of the prop if it has it
* @param {object} node - ObjectExpression node
* @param {string} propName - name of the prop to look for
* @param {string[]} seenProps
*/
function findObjectProp(node, propName, seenProps) {
if (!node.properties) {
Expand Down
6 changes: 3 additions & 3 deletions lib/rules/no-unknown-property.js
Expand Up @@ -157,8 +157,8 @@ function isTagName(node) {

/**
* Extracts the tag name for the JSXAttribute
* @param {Object} node - JSXAttribute being tested.
* @returns {String} tag name
* @param {JSXAttribute} node - JSXAttribute being tested.
* @returns {String|null} tag name
*/
function getTagName(node) {
if (node && node.parent && node.parent.name && node.parent.name) {
Expand Down Expand Up @@ -193,7 +193,7 @@ function getStandardName(name) {
if (SVGDOM_ATTRIBUTE_NAMES[name]) {
return SVGDOM_ATTRIBUTE_NAMES[name];
}
let i;
let i = -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be useless, but I assume tells tsc what the type of i is. It could also be set to 0, but -1 is clearer semantically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If i is not initialized, it could potentially be undefined, that would make tsc reject DOM_PROPERTY_NAMES[i].

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[undefined] on an object without that property is safely undefined, that's just the type system being overly strict :-)

const found = DOM_PROPERTY_NAMES.some((element, index) => {
i = index;
return element.toLowerCase() === name;
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/no-unused-prop-types.js
Expand Up @@ -82,7 +82,7 @@ module.exports = {
/**
* Used to recursively loop through each declared prop type
* @param {Object} component The component to process
* @param {Array} props List of props to validate
* @param {ASTNode[]|true} props List of props to validate
*/
function reportUnusedPropType (component, props) {
// Skip props that check instances
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/prefer-stateless-function.js
Expand Up @@ -137,7 +137,7 @@ module.exports = {
* Checks whether the parameters of a constructor and the arguments of `super()`
* have the same values or not.
* @see ESLint no-useless-constructor rule
* @param {ASTNode} ctorParams - The parameters of a constructor to check.
* @param {ASTNode[]} ctorParams - The parameters of a constructor to check.
* @param {ASTNode} superArgs - The arguments of `super()` to check.
* @returns {boolean} `true` if those have the same values.
*/
Expand Down
8 changes: 4 additions & 4 deletions lib/rules/static-property-placement.js
Expand Up @@ -102,17 +102,17 @@ module.exports = {

/**
* Check if we should report this property node
* @param node
* @param expectedRule
* @param {ASTNode} node
* @param {string} expectedRule
*/
function reportNodeIncorrectlyPositioned(node, expectedRule) {
// Detect if this node is an expected property declaration adn return the property name
const name = classProperties.find(propertyName => {
if (propertiesToCheck[propertyName](node)) {
return propertyName;
return !!propertyName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming the return value of reportNodeIncorrectlyPositioned is always used in a truthy/falsy position, this just returns true instead of "truthy"…

}

return null;
return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and false instead of "falsy".

});

// If name is set but the configured rule does not match expected then report error
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/style-prop-object.js
Expand Up @@ -24,7 +24,7 @@ module.exports = {

create: function(context) {
/**
* @param {object} node An Identifier node
* @param {ASTNode} expression An Identifier node
*/
function isNonNullaryLiteral(expression) {
return expression.type === 'Literal' && expression.value !== null;
Expand Down
29 changes: 29 additions & 0 deletions lib/types.d.ts
@@ -0,0 +1,29 @@
import eslint from 'eslint';
import estree from 'estree';

declare global {
interface ASTNode extends estree.BaseNode {
[_: string]: any; // TODO: fixme
}
type Scope = eslint.Scope.Scope;
type Token = eslint.AST.Token;
type Fixer = eslint.Rule.RuleFixer;
type JSXAttribute = ASTNode;
type JSXSpreadAttribute = ASTNode;

interface Context extends eslint.SourceCode {
getFirstTokens(node: estree.Node | ASTNode, options?: eslint.SourceCode.CursorWithCountOptions): eslint.AST.Token[];
}

type TypeDeclarationBuilder = (annotation: ASTNode, parentName: string, seen: Set<typeof annotation>) => object;

type TypeDeclarationBuilders = {
[k in string]: TypeDeclarationBuilder;
};

type UnionTypeDefinitionChildren = unknown[];
type UnionTypeDefinition = {
type: 'union' | 'shape';
children: UnionTypeDefinitionChildren | true;
};
}
6 changes: 3 additions & 3 deletions lib/util/Components.js
Expand Up @@ -258,7 +258,7 @@ function componentRule(rule, context) {
/**
* Check if variable is destructured from pragma import
*
* @param {variable} String The variable name to check
* @param {string} variable The variable name to check
* @returns {Boolean} True if createElement is destructured from the pragma
*/
isDestructuredFromPragmaImport: function(variable) {
Expand Down Expand Up @@ -351,7 +351,7 @@ function componentRule(rule, context) {
* Check if the node is returning JSX
*
* @param {ASTNode} ASTnode The AST node being checked
* @param {Boolean} strict If true, in a ternary condition the node must return JSX in both cases
* @param {Boolean} [strict] If true, in a ternary condition the node must return JSX in both cases
* @returns {Boolean} True if the node is returning JSX, false if not
*/
isReturningJSX: function(ASTnode, strict) {
Expand Down Expand Up @@ -413,7 +413,7 @@ function componentRule(rule, context) {
* Check if the node is returning JSX or null
*
* @param {ASTNode} ASTnode The AST node being checked
* @param {Boolean} strict If true, in a ternary condition the node must return JSX in both cases
* @param {Boolean} [strict] If true, in a ternary condition the node must return JSX in both cases
* @returns {Boolean} True if the node is returning JSX or null, false if not
*/
isReturningJSXOrNull(ASTNode, strict) {
Expand Down
1 change: 1 addition & 0 deletions lib/util/annotations.js
Expand Up @@ -8,6 +8,7 @@
/**
* Checks if we are declaring a `props` argument with a flow type annotation.
* @param {ASTNode} node The AST node being checked.
* @param {Object} context
* @returns {Boolean} True if the node is a type annotated props declaration, false if not.
*/
function isAnnotatedFunctionPropsDeclaration(node, context) {
Expand Down
10 changes: 5 additions & 5 deletions lib/util/ast.js
Expand Up @@ -6,7 +6,7 @@
/**
* Find a return statment in the current node
*
* @param {ASTNode} ASTnode The AST node being checked
* @param {ASTNode} node The AST node being checked
*/
function findReturnStatement(node) {
if (
Expand Down Expand Up @@ -114,7 +114,7 @@ function isNodeFirstInLine(context, node) {

/**
* Checks if the node is a function or arrow function expression.
* @param {Object} context The node to check
* @param {ASTNode} node The node to check
* @return {Boolean} true if it's a function-like expression
*/
function isFunctionLikeExpression(node) {
Expand All @@ -123,7 +123,7 @@ function isFunctionLikeExpression(node) {

/**
* Checks if the node is a function.
* @param {Object} context The node to check
* @param {ASTNode} node The node to check
* @return {Boolean} true if it's a function
*/
function isFunction(node) {
Expand All @@ -132,7 +132,7 @@ function isFunction(node) {

/**
* Checks if the node is an arrow function.
* @param {Object} context The node to check
* @param {ASTNode} node The node to check
* @return {Boolean} true if it's an arrow function
*/
function isArrowFunction(node) {
Expand All @@ -141,7 +141,7 @@ function isArrowFunction(node) {

/**
* Checks if the node is a class.
* @param {Object} context The node to check
* @param {ASTNode} node The node to check
* @return {Boolean} true if it's a class
*/
function isClass(node) {
Expand Down
2 changes: 1 addition & 1 deletion lib/util/defaultProps.js
Expand Up @@ -70,7 +70,7 @@ module.exports = function defaultPropsInstructions(context, components, utils) {
/**
* Adds defaultProps to the component passed in.
* @param {ASTNode} component The component to add the defaultProps to.
* @param {String[]|String} defaultProps defaultProps to add to the component or the string "unresolved"
* @param {Object[]|'unresolved'} defaultProps defaultProps to add to the component or the string "unresolved"
* if this component has defaultProps that can't be resolved.
* @returns {void}
*/
Expand Down
7 changes: 6 additions & 1 deletion lib/util/linkComponents.js
Expand Up @@ -3,12 +3,17 @@
*/
'use strict';

/** TODO: type {(string | { name: string, linkAttribute: string })[]} */
/** @type {any} */
const DEFAULT_LINK_COMPONENTS = ['a'];
const DEFAULT_LINK_ATTRIBUTE = 'href';

function getLinkComponents(context) {
const settings = context.settings || {};
return new Map(DEFAULT_LINK_COMPONENTS.concat(settings.linkComponents || []).map(value => {
const linkComponents = /** @type {typeof DEFAULT_LINK_COMPONENTS} */ (
DEFAULT_LINK_COMPONENTS.concat(settings.linkComponents || [])
);
return new Map(linkComponents.map(value => {
if (typeof value === 'string') {
return [value, DEFAULT_LINK_ATTRIBUTE];
}
Expand Down