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

[evcohen/jsx-ast-utils#70] Support OptionalMemberExpression AST nodes #77

Merged
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion __tests__/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ const parser = require('babylon');

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
26 changes: 20 additions & 6 deletions __tests__/src/getPropValue-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,20 @@ describe('getPropValue', () => {

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

it('should evaluate to a correct representation of member expression with a nullable member', () => {
// This tell will not throw when Babel is upgraded from 6 to 7. Remove
// the throw expectation wrapper at that time.
// eslint-disable-next-line no-undef
expect(() => {
const prop = extractProp('<div foo={bar?.baz} />');

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

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

describe('Call expression', () => {
Expand Down Expand Up @@ -383,7 +397,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 +416,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 +483,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 +492,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 +502,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 +511,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
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: 2 additions & 2 deletions src/values/expressions/ArrayExpression.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import getValue from './index';
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I had to get rid of all these circular dependencies.


/**
* 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) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
return value.elements.map(element => getValue(element));
}
5 changes: 2 additions & 3 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 @@ -10,6 +7,8 @@ import getValue from './index';
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromBinaryExpression(value) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
const { operator, left, right } = value;
const leftVal = getValue(left);
const rightVal = getValue(right);
Expand Down
5 changes: 2 additions & 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 @@ -10,7 +8,8 @@ import getValue from './index';
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromBindExpression(value) {
// console.log(value);
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
const callee = getValue(value.callee);

// If value.object === null, the callee must be a MemberExpression.
Expand Down
4 changes: 2 additions & 2 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 @@ -10,5 +8,7 @@ import getValue from './index';
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromCallExpression(value) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
return getValue(value.callee);
}
4 changes: 2 additions & 2 deletions src/values/expressions/ConditionalExpression.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
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) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
const {
test,
alternate,
Expand Down
4 changes: 2 additions & 2 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 @@ -9,6 +7,8 @@ import getValue from './index';
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromLogicalExpression(value) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
const { operator, left, right } = value;
const leftVal = getValue(left);
const rightVal = getValue(right);
Expand Down
4 changes: 2 additions & 2 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 @@ -9,5 +7,7 @@ import getValue from './index';
* and maintaing `obj.property` convention.
*/
export default function extractValueFromMemberExpression(value) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
return `${getValue(value.object)}.${getValue(value.property)}`;
}
6 changes: 3 additions & 3 deletions src/values/expressions/ObjectExpression.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
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) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
return value.properties.reduce((obj, property) => {
const object = Object.assign({}, obj);
// Support types: SpreadProperty and ExperimentalSpreadProperty
if (/^(?:Experimental)?SpreadProperty$/.test(property.type)) {
if (/^(?:Experimental)?Spread(?:Property|Element)$/.test(property.type)) {
if (property.argument.type === 'ObjectExpression') {
return Object.assign(object, extractValueFromObjectExpression(property.argument));
}
Expand Down
13 changes: 13 additions & 0 deletions src/values/expressions/OptionalMemberExpression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* 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) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
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
4 changes: 2 additions & 2 deletions src/values/expressions/UnaryExpression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import getValue from './index';

/**
* Extractor function for a UnaryExpression type value node.
* A unary expression is an expression with a unary operator.
Expand All @@ -9,6 +7,8 @@ import getValue from './index';
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromUnaryExpression(value) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
const { operator, argument } = value;

switch (operator) {
Expand Down
4 changes: 2 additions & 2 deletions src/values/expressions/UpdateExpression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import getValue from './index';

/**
* Extractor function for an UpdateExpression type value node.
* An update expression is an expression with an update operator.
Expand All @@ -9,6 +7,8 @@ import getValue from './index';
* @returns - The extracted value converted to correct type.
*/
export default function extractValueFromUpdateExpression(value) {
// eslint-disable-next-line global-require
const getValue = require('./index.js').default;
const { operator, argument, prefix } = value;

let val = getValue(argument);
Expand Down
Loading