1 | var createNodeKey = require('./create-node-key').createNodeKey;
|
2 | var AstNodeTypes = require("./ast-node-types.js");
|
3 | var SlJsInfra = require("sl-js-infra").SlJsInfra;
|
4 |
|
5 | /*
|
6 | When working in React, components are being generated by the "_createClass" method of the framework.
|
7 | As a result, we have an issue when we try to map it back to source maps.
|
8 | The method make sure to verify if a component is a React component by going through the parent nodes
|
9 | fpr a specific node, and verifying that they have the same pattern as the expected code.
|
10 |
|
11 | React Code
|
12 | ================== START CODE ============
|
13 | import React, { Component } from 'react';
|
14 | import logo from './logo.svg';
|
15 | import './App.css';
|
16 |
|
17 | class App extends Component {
|
18 | someFunc(){
|
19 | console.log("hezi func")
|
20 | }
|
21 | }
|
22 |
|
23 | export default App;
|
24 | ================== END CODE ============
|
25 |
|
26 | This code generates the following code
|
27 | ================== START CODE ============
|
28 | _createClass(App, [{
|
29 | key: 'someFunc',
|
30 | value: function someFunc() {
|
31 | console.log("Some func is invoked");
|
32 | }
|
33 | }]);
|
34 | ================== END CODE ============
|
35 |
|
36 | So basically we are searching for the "value" node, the array which contains it and the "_createClass" method.
|
37 | * */
|
38 | function isReact(node, nodeToParent){
|
39 | if (node.type != "FunctionExpression")
|
40 | return false;
|
41 | var key = createNodeKey(node);
|
42 | var valueNode = nodeToParent[key];
|
43 | if (valueNode == null)
|
44 | return false;
|
45 | if (valueNode.key == null || (valueNode.key !=null && valueNode.key.name != "value"))
|
46 | return false; //That's note the 'value' node. Return.
|
47 | key = createNodeKey(valueNode);
|
48 | parent = nodeToParent[key];
|
49 | if (parent == null)
|
50 | return false;
|
51 | var objectNode = parent;
|
52 | key = createNodeKey(objectNode);
|
53 | arrayNode = nodeToParent[key];
|
54 | if (arrayNode == null || arrayNode.type != "ArrayExpression")
|
55 | return false;
|
56 | key = createNodeKey(arrayNode);
|
57 | var createClassNode = nodeToParent[key];
|
58 | if (createClassNode == null || createClassNode.callee == null){
|
59 | return false;
|
60 | }
|
61 | var result = createClassNode.callee.name == "_createClass";
|
62 | return result;
|
63 | }
|
64 |
|
65 | /**
|
66 |
|
67 | * */
|
68 | function guessMethodLocation(node, nodeToParent) {
|
69 | if (isReact(node, nodeToParent) && node.type == AstNodeTypes.FunctionExpression) {
|
70 | return node.body.loc;
|
71 | }
|
72 |
|
73 | /* According to this link, Istanbul uses the "node.id.loc" for FunctionDeclaration and FunctionExpression.
|
74 | * https://github.com/istanbuljs/istanbuljs/blob/cbd1c1473da0dc34051c332170544529d59eda03/packages/istanbul-lib-instrument/src/visitor.js#L216
|
75 | */
|
76 | if (!SlJsInfra.SlEnvVars.isUseIstanbul() && shouldUseLocFromID(node) && node.id && node.id.loc) {
|
77 | return node.id.loc;
|
78 | }
|
79 |
|
80 |
|
81 | /*
|
82 | In typescript, in case of below code, diferrent location recieved from source maps and babel parser.
|
83 | export function foo(){
|
84 |
|
85 | }
|
86 | Source maps: column 0
|
87 | Babel parser: cloumn 7 (the 'function' woord.
|
88 | Here we fix the location to be column 0 (export statement location)
|
89 | */
|
90 | if(node.type === "FunctionDeclaration"){
|
91 | var key = createNodeKey(node);
|
92 | var parentNode = nodeToParent[key];
|
93 | if(parentNode.type == "ExportDefaultDeclaration" || parentNode.type == "ExportNamedDeclaration") {
|
94 | return parentNode.loc
|
95 | }
|
96 | }
|
97 | return node.loc;
|
98 | }
|
99 |
|
100 | function shouldUseLocFromID(node) {
|
101 | return node.type === AstNodeTypes.FunctionDeclaration || node.type === AstNodeTypes.FunctionExpression;
|
102 | }
|
103 |
|
104 | module.exports.guessMethodLocation = guessMethodLocation; |
\ | No newline at end of file |