Skip to content

Commit

Permalink
Re-write Components as a class
Browse files Browse the repository at this point in the history
  • Loading branch information
jseminck committed Nov 14, 2017
1 parent 64cf2d7 commit 8d66521
Showing 1 changed file with 137 additions and 135 deletions.
272 changes: 137 additions & 135 deletions lib/util/Components.js
Expand Up @@ -11,164 +11,166 @@ const variableUtil = require('./variable');
const pragmaUtil = require('./pragma');
const astUtil = require('./ast');

const usedPropTypesAreEquivalent = (propA, propB) => {
if (propA.name === propB.name) {
if (!propA.allNames && !propB.allNames) {
return true;
} else if (Array.isArray(propA.allNames) && Array.isArray(propB.allNames) && propA.allNames.join('') === propB.allNames.join('')) {
return true;
}
return false;
}
return false;
};

const mergeUsedPropTypes = (propsList, newPropsList) => {
const propsToAdd = [];
newPropsList.forEach(newProp => {
const newPropisAlreadyInTheList = propsList.some(prop => usedPropTypesAreEquivalent(prop, newProp));
if (!newPropisAlreadyInTheList) {
propsToAdd.push(newProp);
}
});
return propsList.concat(propsToAdd);
};


/**
* Components
* @class
*/
function Components() {
this._list = {};
this._getId = function(node) {
class Components {
constructor() {
this._list = {};
}

_getId(node) {
return node && node.range.join(':');
};
}
}

/**
* Add a node to the components list, or update it if it's already in the list
*
* @param {ASTNode} node The AST node being added.
* @param {Number} confidence Confidence in the component detection (0=banned, 1=maybe, 2=yes)
* @returns {Object} Added component object
*/
Components.prototype.add = function(node, confidence) {
const id = this._getId(node);
if (this._list[id]) {
if (confidence === 0 || this._list[id].confidence === 0) {
this._list[id].confidence = 0;
} else {
this._list[id].confidence = Math.max(this._list[id].confidence, confidence);
/**
* Add a node to the components list, or update it if it's already in the list
*
* @param {ASTNode} node The AST node being added.
* @param {Number} confidence Confidence in the component detection (0=banned, 1=maybe, 2=yes)
* @returns {Object} Added component object
*/
add(node, confidence) {
const id = this._getId(node);
if (this._list[id]) {
if (confidence === 0 || this._list[id].confidence === 0) {
this._list[id].confidence = 0;
} else {
this._list[id].confidence = Math.max(this._list[id].confidence, confidence);
}
return this._list[id];
}
this._list[id] = {
node: node,
confidence: confidence
};
return this._list[id];
}
this._list[id] = {
node: node,
confidence: confidence
};
return this._list[id];
};

/**
* Find a component in the list using its node
*
* @param {ASTNode} node The AST node being searched.
* @returns {Object} Component object, undefined if the component is not found
*/
Components.prototype.get = function(node) {
const id = this._getId(node);
return this._list[id];
};

/**
* Update a component in the list
*
* @param {ASTNode} node The AST node being updated.
* @param {Object} props Additional properties to add to the component.
*/
Components.prototype.set = function(node, props) {
while (node && !this._list[this._getId(node)]) {
node = node.parent;
}
if (!node) {
return;
}
const id = this._getId(node);
let copyUsedPropTypes;
if (this._list[id]) {
// usedPropTypes is an array. _extend replaces existing array with a new one which caused issue #1309.
// preserving original array so it can be merged later on.
copyUsedPropTypes = this._list[id].usedPropTypes && this._list[id].usedPropTypes.slice();
/**
* Find a component in the list using its node
*
* @param {ASTNode} node The AST node being searched.
* @returns {Object} Component object, undefined if the component is not found
*/
get(node) {
const id = this._getId(node);
return this._list[id];
}
this._list[id] = util._extend(this._list[id], props);
if (this._list[id] && props.usedPropTypes) {
this._list[id].usedPropTypes = mergeUsedPropTypes(copyUsedPropTypes || [], props.usedPropTypes);

/**
* Update a component in the list
*
* @param {ASTNode} node The AST node being updated.
* @param {Object} props Additional properties to add to the component.
*/
set(node, props) {
while (node && !this._list[this._getId(node)]) {
node = node.parent;
}
if (!node) {
return;
}
const id = this._getId(node);
let copyUsedPropTypes;
if (this._list[id]) {
// usedPropTypes is an array. _extend replaces existing array with a new one which caused issue #1309.
// preserving original array so it can be merged later on.
copyUsedPropTypes = this._list[id].usedPropTypes && this._list[id].usedPropTypes.slice();
}
this._list[id] = util._extend(this._list[id], props);
if (this._list[id] && props.usedPropTypes) {
this._list[id].usedPropTypes = this._mergeUsedPropTypes(copyUsedPropTypes || [], props.usedPropTypes);
}
}
};

/**
* Return the components list
* Components for which we are not confident are not returned
*
* @returns {Object} Components list
*/
Components.prototype.list = function() {
const list = {};
const usedPropTypes = {};
// Find props used in components for which we are not confident
for (const i in this._list) {
if (!has(this._list, i) || this._list[i].confidence >= 2) {
continue;
/**
* Return the components list
* Components for which we are not confident are not returned
*
* @returns {Object} Components list
*/
list() {
const list = {};
const usedPropTypes = {};
// Find props used in components for which we are not confident
for (const i in this._list) {
if (!has(this._list, i) || this._list[i].confidence >= 2) {
continue;
}
let component = null;
let node = null;
node = this._list[i].node;
while (!component && node.parent) {
node = node.parent;
// Stop moving up if we reach a decorator
if (node.type === 'Decorator') {
break;
}
component = this.get(node);
}
if (component) {
const newUsedProps = (this._list[i].usedPropTypes || []).filter(propType => !propType.node || propType.node.kind !== 'init');

const componentId = this._getId(component.node);
usedPropTypes[componentId] = (usedPropTypes[componentId] || []).concat(newUsedProps);
}
}
let component = null;
let node = null;
node = this._list[i].node;
while (!component && node.parent) {
node = node.parent;
// Stop moving up if we reach a decorator
if (node.type === 'Decorator') {
break;
// Assign used props in not confident components to the parent component
for (const j in this._list) {
if (!has(this._list, j) || this._list[j].confidence < 2) {
continue;
}
const id = this._getId(this._list[j].node);
list[j] = this._list[j];
if (usedPropTypes[id]) {
list[j].usedPropTypes = (list[j].usedPropTypes || []).concat(usedPropTypes[id]);
}
component = this.get(node);
}
if (component) {
const newUsedProps = (this._list[i].usedPropTypes || []).filter(propType => !propType.node || propType.node.kind !== 'init');
return list;
}

const componentId = this._getId(component.node);
usedPropTypes[componentId] = (usedPropTypes[componentId] || []).concat(newUsedProps);
/**
* Return the length of the components list
* Components for which we are not confident are not counted
*
* @returns {Number} Components list length
*/
length() {
let length = 0;
for (const i in this._list) {
if (!has(this._list, i) || this._list[i].confidence < 2) {
continue;
}
length++;
}
return length;
}
// Assign used props in not confident components to the parent component
for (const j in this._list) {
if (!has(this._list, j) || this._list[j].confidence < 2) {
continue;
}
const id = this._getId(this._list[j].node);
list[j] = this._list[j];
if (usedPropTypes[id]) {
list[j].usedPropTypes = (list[j].usedPropTypes || []).concat(usedPropTypes[id]);
}

_mergeUsedPropTypes(propsList, newPropsList) {
const propsToAdd = [];
newPropsList.forEach(newProp => {
const newPropisAlreadyInTheList = propsList.some(prop => this._usedPropTypesAreEquivalent(prop, newProp));
if (!newPropisAlreadyInTheList) {
propsToAdd.push(newProp);
}
});
return propsList.concat(propsToAdd);
}
return list;
};

/**
* Return the length of the components list
* Components for which we are not confident are not counted
*
* @returns {Number} Components list length
*/
Components.prototype.length = function() {
let length = 0;
for (const i in this._list) {
if (!has(this._list, i) || this._list[i].confidence < 2) {
continue;
_usedPropTypesAreEquivalent(propA, propB) {
if (propA.name === propB.name) {
if (!propA.allNames && !propB.allNames) {
return true;
} else if (Array.isArray(propA.allNames) && Array.isArray(propB.allNames) && propA.allNames.join('') === propB.allNames.join('')) {
return true;
}
return false;
}
length++;
return false;
}
return length;
};
}

function componentRule(rule, context) {
const createClass = pragmaUtil.getCreateClassFromContext(context);
Expand Down

0 comments on commit 8d66521

Please sign in to comment.