| function getTrace(node) { |
| function shouldPutToTrace(syntax) { |
| if (syntax === null) { |
| return false; |
| } |
| |
| return ( |
| syntax.type === 'Type' || |
| syntax.type === 'Property' || |
| syntax.type === 'Keyword' |
| ); |
| } |
| |
| function hasMatch(matchNode) { |
| if (Array.isArray(matchNode.match)) { |
| // use for-loop for better perfomance |
| for (var i = 0; i < matchNode.match.length; i++) { |
| if (hasMatch(matchNode.match[i])) { |
| if (shouldPutToTrace(matchNode.syntax)) { |
| result.unshift(matchNode.syntax); |
| } |
| |
| return true; |
| } |
| } |
| } else if (matchNode.node === node) { |
| result = shouldPutToTrace(matchNode.syntax) |
| ? [matchNode.syntax] |
| : []; |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| var result = null; |
| |
| if (this.matched !== null) { |
| hasMatch(this.matched); |
| } |
| |
| return result; |
| } |
| |
| function testNode(match, node, fn) { |
| var trace = getTrace.call(match, node); |
| |
| if (trace === null) { |
| return false; |
| } |
| |
| return trace.some(fn); |
| } |
| |
| function isType(node, type) { |
| return testNode(this, node, function(matchNode) { |
| return matchNode.type === 'Type' && matchNode.name === type; |
| }); |
| } |
| |
| function isProperty(node, property) { |
| return testNode(this, node, function(matchNode) { |
| return matchNode.type === 'Property' && matchNode.name === property; |
| }); |
| } |
| |
| function isKeyword(node) { |
| return testNode(this, node, function(matchNode) { |
| return matchNode.type === 'Keyword'; |
| }); |
| } |
| |
| module.exports = { |
| getTrace: getTrace, |
| isType: isType, |
| isProperty: isProperty, |
| isKeyword: isKeyword |
| }; |