Skip to content

Commit

Permalink
[#70] Support OptionalMemberExpression AST nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
jessebeach committed Mar 18, 2019
1 parent a9d4159 commit 2222861
Show file tree
Hide file tree
Showing 23 changed files with 137 additions and 113 deletions.
6 changes: 5 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
{
"presets": ["es2015"]
"presets": ["@babel/preset-env"],
"plugins": [
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-object-rest-spread",
],
}
10 changes: 8 additions & 2 deletions __tests__/helper.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import getProp from '../src/getProp';

const parser = require('babylon');
const parser = require('@babel/parser');

function parse(code) {
return parser.parse(code, {
plugins: ['jsx', 'functionBind', 'estree', 'objectRestSpread'],
plugins: [
'estree',
'functionBind',
'jsx',
'objectRestSpread',
'optionalChaining',
],
});
}

Expand Down
12 changes: 6 additions & 6 deletions __tests__/src/getPropLiteralValue-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ describe('getLiteralPropValue', () => {

// -"bar" => NaN
const expected = true;
const actual = isNaN(getLiteralPropValue(prop));
const actual = Number.isNaN(getLiteralPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -277,7 +277,7 @@ describe('getLiteralPropValue', () => {

// +"bar" => NaN
const expected = true;
const actual = isNaN(getLiteralPropValue(prop));
const actual = Number.isNaN(getLiteralPropValue(prop));

assert.equal(expected, actual);
});
Expand Down Expand Up @@ -344,7 +344,7 @@ describe('getLiteralPropValue', () => {

// ++"bar" => NaN
const expected = true;
const actual = isNaN(getLiteralPropValue(prop));
const actual = Number.isNaN(getLiteralPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -354,7 +354,7 @@ describe('getLiteralPropValue', () => {

// --"bar" => NaN
const expected = true;
const actual = isNaN(getLiteralPropValue(prop));
const actual = Number.isNaN(getLiteralPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -364,7 +364,7 @@ describe('getLiteralPropValue', () => {

// "bar"++ => NaN
const expected = true;
const actual = isNaN(getLiteralPropValue(prop));
const actual = Number.isNaN(getLiteralPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -374,7 +374,7 @@ describe('getLiteralPropValue', () => {

// "bar"-- => NaN
const expected = true;
const actual = isNaN(getLiteralPropValue(prop));
const actual = Number.isNaN(getLiteralPropValue(prop));

assert.equal(expected, actual);
});
Expand Down
21 changes: 15 additions & 6 deletions __tests__/src/getPropValue-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,15 @@ describe('getPropValue', () => {

assert.equal(expected, actual);
});

it('should evaluate to a correct representation of member expression with a nullable member', () => {
const prop = extractProp('<div foo={bar?.baz} />');

const expected = 'bar?.baz';
const actual = getPropValue(prop);

assert.equal(expected, actual);
});
});

describe('Call expression', () => {
Expand Down Expand Up @@ -383,7 +392,7 @@ describe('getPropValue', () => {

// -"bar" => NaN
const expected = true;
const actual = isNaN(getPropValue(prop));
const actual = Number.isNaN(getPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -402,7 +411,7 @@ describe('getPropValue', () => {

// +"bar" => NaN
const expected = true;
const actual = isNaN(getPropValue(prop));
const actual = Number.isNaN(getPropValue(prop));

assert.equal(expected, actual);
});
Expand Down Expand Up @@ -469,7 +478,7 @@ describe('getPropValue', () => {

// ++"bar" => NaN
const expected = true;
const actual = isNaN(getPropValue(prop));
const actual = Number.isNaN(getPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -478,7 +487,7 @@ describe('getPropValue', () => {
const prop = extractProp('<div foo={--bar} />');

const expected = true;
const actual = isNaN(getPropValue(prop));
const actual = Number.isNaN(getPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -488,7 +497,7 @@ describe('getPropValue', () => {

// "bar"++ => NaN
const expected = true;
const actual = isNaN(getPropValue(prop));
const actual = Number.isNaN(getPropValue(prop));

assert.equal(expected, actual);
});
Expand All @@ -497,7 +506,7 @@ describe('getPropValue', () => {
const prop = extractProp('<div foo={bar--} />');

const expected = true;
const actual = isNaN(getPropValue(prop));
const actual = Number.isNaN(getPropValue(prop));

assert.equal(expected, actual);
});
Expand Down
2 changes: 1 addition & 1 deletion elementType.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = require('./lib').elementType; // eslint-disable-line import/no-unresolved
module.exports = require('./lib').elementType; // eslint-disable-line import/no-unresolved
29 changes: 16 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,22 @@
"test:watch": "npm test -- --watch"
},
"devDependencies": {
"babel-cli": "^6.14.0",
"babel-core": "^6.14.0",
"babel-eslint": "^7.0.0",
"babel-jest": "^20.0.0",
"babel-polyfill": "^6.16.0",
"babel-preset-es2015": "^6.14.0",
"babylon": "^6.17.2",
"coveralls": "^2.11.8",
"eslint": "^3.12.1",
"eslint-config-airbnb-base": "^11.1.0",
"eslint-plugin-import": "^2.2.0",
"jest": "^20.0.0",
"rimraf": "^2.5.2"
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/parser": "^7.3.4",
"@babel/plugin-proposal-object-rest-spread": "^7.3.4",
"@babel/plugin-proposal-optional-chaining": "^7.2.0",
"@babel/preset-env": "^7.3.4",
"babel-eslint": "^10.0.1",
"babel-jest": "^24.5.0",
"coveralls": "^3.0.3",
"eslint": "^5.15.2",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-plugin-import": "^2.16.0",
"install": "^0.12.2",
"jest": "^24.5.0",
"npm": "^6.9.0",
"rimraf": "^2.6.3"
},
"engines": {
"node": ">=4.0"
Expand Down
4 changes: 3 additions & 1 deletion src/elementType.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export default function elementType(node = {}) {
if (name.type === 'JSXMemberExpression') {
const { object = {}, property = {} } = name;
return resolveMemberExpressions(object, property);
} else if (name.type === 'JSXNamespacedName') {
}

if (name.type === 'JSXNamespacedName') {
return `${name.namespace.name}:${name.name.name}`;
}

Expand Down
6 changes: 3 additions & 3 deletions src/getProp.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export default function getProp(props = [], prop = '', options = DEFAULT_OPTIONS
return false;
}

const currentProp = options.ignoreCase ?
propName(attribute).toUpperCase() :
propName(attribute);
const currentProp = options.ignoreCase
? propName(attribute).toUpperCase()
: propName(attribute);

return propToFind === currentProp;
});
Expand Down
6 changes: 3 additions & 3 deletions src/hasProp.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export default function hasProp(props = [], prop = '', options = DEFAULT_OPTIONS
return !options.spreadStrict;
}

const currentProp = options.ignoreCase ?
propName(attribute).toUpperCase() :
propName(attribute);
const currentProp = options.ignoreCase
? propName(attribute).toUpperCase()
: propName(attribute);

return propToCheck === currentProp;
});
Expand Down
4 changes: 3 additions & 1 deletion src/values/Literal.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ export default function extractValueFromLiteral(value) {
const normalizedStringValue = typeof extractedValue === 'string' && extractedValue.toLowerCase();
if (normalizedStringValue === 'true') {
return true;
} else if (normalizedStringValue === 'false') {
}

if (normalizedStringValue === 'false') {
return false;
}

Expand Down
4 changes: 1 addition & 3 deletions src/values/expressions/ArrayExpression.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import getValue from './index';

/**
* Extractor function for an ArrayExpression type value node.
* An array expression is an expression with [] syntax.
*
* @returns - An array of the extracted elements.
*/
export default function extractValueFromArrayExpression(value) {
export default function extractValueFromArrayExpression(value, getValue) {
return value.elements.map(element => getValue(element));
}
5 changes: 1 addition & 4 deletions src/values/expressions/BinaryExpression.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import getValue from './index';


/**
* Extractor function for a BinaryExpression type value node.
* A binary expression has a left and right side separated by an operator
Expand All @@ -9,7 +6,7 @@ import getValue from './index';
* @param - value - AST Value object with type `BinaryExpression`
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromBinaryExpression(value) {
export default function extractValueFromBinaryExpression(value, getValue) {
const { operator, left, right } = value;
const leftVal = getValue(left);
const rightVal = getValue(right);
Expand Down
4 changes: 1 addition & 3 deletions src/values/expressions/BindExpression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import getValue from './index';

/**
* Extractor function for a BindExpression type value node.
* A bind expression looks like `::this.foo`
Expand All @@ -9,7 +7,7 @@ import getValue from './index';
* @param - value - AST Value object with type `BindExpression`
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromBindExpression(value) {
export default function extractValueFromBindExpression(value, getValue) {
// console.log(value);
const callee = getValue(value.callee);

Expand Down
4 changes: 1 addition & 3 deletions src/values/expressions/CallExpression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import getValue from './index';

/**
* Extractor function for a CallExpression type value node.
* A call expression looks like `bar()`
Expand All @@ -9,6 +7,6 @@ import getValue from './index';
* @param - value - AST Value object with type `CallExpression`
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromCallExpression(value) {
export default function extractValueFromCallExpression(value, getValue) {
return getValue(value.callee);
}
4 changes: 1 addition & 3 deletions src/values/expressions/ConditionalExpression.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import getValue from './index';

/**
* Extractor function for a ConditionalExpression type value node.
*
* @param - value - AST Value object with type `ConditionalExpression`
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromConditionalExpression(value) {
export default function extractValueFromConditionalExpression(value, getValue) {
const {
test,
alternate,
Expand Down
4 changes: 1 addition & 3 deletions src/values/expressions/LogicalExpression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import getValue from './index';

/**
* Extractor function for a LogicalExpression type value node.
* A logical expression is `a && b` or `a || b`, so we evaluate both sides
Expand All @@ -8,7 +6,7 @@ import getValue from './index';
* @param - value - AST Value object with type `LogicalExpression`
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromLogicalExpression(value) {
export default function extractValueFromLogicalExpression(value, getValue) {
const { operator, left, right } = value;
const leftVal = getValue(left);
const rightVal = getValue(right);
Expand Down
4 changes: 1 addition & 3 deletions src/values/expressions/MemberExpression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import getValue from './index';

/**
* Extractor function for a MemberExpression type value node.
* A member expression is accessing a property on an object `obj.property`.
Expand All @@ -8,6 +6,6 @@ import getValue from './index';
* @returns - The extracted value converted to correct type
* and maintaing `obj.property` convention.
*/
export default function extractValueFromMemberExpression(value) {
export default function extractValueFromMemberExpression(value, getValue) {
return `${getValue(value.object)}.${getValue(value.property)}`;
}
11 changes: 6 additions & 5 deletions src/values/expressions/ObjectExpression.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import getValue from './index';

/**
* Extractor function for an ObjectExpression type value node.
* An object expression is using {}.
*
* @returns - a representation of the object
*/
export default function extractValueFromObjectExpression(value) {
export default function extractValueFromObjectExpression(value, getValue) {
return value.properties.reduce((obj, property) => {
const object = Object.assign({}, obj);
// Support types: SpreadProperty and ExperimentalSpreadProperty
if (/^(?:Experimental)?SpreadProperty$/.test(property.type)) {
if (
/^(?:Experimental)?SpreadProperty$/.test(property.type)
|| property.type === 'SpreadElement'
) {
if (property.argument.type === 'ObjectExpression') {
return Object.assign(object, extractValueFromObjectExpression(property.argument));
return Object.assign(object, extractValueFromObjectExpression(property.argument, getValue));
}
} else {
object[getValue(property.key)] = getValue(property.value);
Expand Down
11 changes: 11 additions & 0 deletions src/values/expressions/OptionalMemberExpression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Extractor function for a OptionalMemberExpression type value node.
* A member expression is accessing a property on an object `obj.property`.
*
* @param - value - AST Value object with type `OptionalMemberExpression`
* @returns - The extracted value converted to correct type
* and maintaing `obj?.property` convention.
*/
export default function extractValueFromOptionalMemberExpression(value, getValue) {
return `${getValue(value.object)}?.${getValue(value.property)}`;
}
8 changes: 6 additions & 2 deletions src/values/expressions/TemplateLiteral.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ export default function extractValueFromTemplateLiteral(value) {
} = part;
if (type === 'TemplateElement') {
return raw + part.value.raw;
} else if (type === 'Identifier') {
}

if (type === 'Identifier') {
return part.name === 'undefined' ? `${raw}${part.name}` : `${raw}{${part.name}}`;
} else if (type.indexOf('Expression') > -1) {
}

if (type.indexOf('Expression') > -1) {
return `${raw}{${type}}`;
}

Expand Down
Loading

0 comments on commit 2222861

Please sign in to comment.