You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2018/11/02 04:53:09 UTC

[GitHub] rtaneja1 closed pull request #994: [NETBEANS-1438] : stackoverflowerror opening .js files

rtaneja1 closed pull request #994: [NETBEANS-1438] : stackoverflowerror opening .js files
URL: https://github.com/apache/incubator-netbeans/pull/994
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/webcommon/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_3.js b/webcommon/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_3.js
new file mode 100644
index 0000000000..89df478d25
--- /dev/null
+++ b/webcommon/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_3.js
@@ -0,0 +1,6 @@
+module.exports = function test() {
+  var test1 = Foo.test2;
+  Foo.test2 = function(err, test3) { return test3; };
+  Foo.test2 = test1;
+};
+
diff --git a/webcommon/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java b/webcommon/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java
index d5964d7ddf..c196fceeb1 100644
--- a/webcommon/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java
+++ b/webcommon/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java
@@ -53,6 +53,10 @@ public void testIssue233298_3() throws Exception {
     public void testIssue233298_4() throws Exception { 
         checkDeclaration("testfiles/coloring/issue233298.js", "a.b^", "a.^b");
     }
+
+    public void testIssue233298_5() throws Exception {
+        checkDeclaration("testfiles/coloring/issue233298_3.js", "Foo.test2 = test^1", "var ^test1 = Foo.test2");
+    }
     
     public void testBasicNavigation_01() throws Exception {
         checkDeclaration("testfiles/model/variables01.js", "var address = new A^ddress(\"Prague\", \"Czech Republic\", 15000)", "function ^Address (town, state, number) {");
diff --git a/webcommon/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java b/webcommon/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java
index fc58224925..1882a8728c 100644
--- a/webcommon/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java
+++ b/webcommon/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java
@@ -29,6 +29,9 @@
 import java.util.List;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
 import org.netbeans.api.annotations.common.NullAllowed;
 import org.netbeans.api.lexer.Token;
 import org.netbeans.api.lexer.TokenHierarchy;
@@ -82,6 +85,8 @@
     
     private static String GLOBAL_DIRECTIVE = "global"; //NOI18N
     
+    private static final Logger LOG = Logger.getLogger(ModelUtils.class.getName());
+    
     public static JsObjectImpl getJsObject (ModelBuilder builder, List<Identifier> fqName, boolean isLHS) {
         if (fqName == null || fqName.isEmpty()) {
             return null;
@@ -1172,14 +1177,17 @@ public static boolean hasDeclaredProperty(JsObject jsObject) {
      * @return
      */
     public static TypeUsage createResolvedType(JsObject parent, TypeUsage typeHere) {
+        int invokeCount = 0;
         String fqn = getFQNFromType(typeHere);
-        return resolveTypes(parent, fqn, typeHere.getOffset());
+        List<TypeUsage> alreadyResolved = new ArrayList<>(); 
+        return resolveTypes(parent, fqn, typeHere.getOffset(), alreadyResolved, invokeCount);
     }
 
     /* @return TypeUsage with generated typename string 
      */
-    private static TypeUsage resolveTypes(JsObject parent, String fqn, int offset) {
+    private static TypeUsage resolveTypes(JsObject parent, String fqn, int offset, List<TypeUsage> alreadyResolved, int invokeCount) {
 
+        invokeCount++;
         String name = fqn;
         StringBuilder props = new StringBuilder();
         int indx = fqn.indexOf(".");
@@ -1187,42 +1195,49 @@ private static TypeUsage resolveTypes(JsObject parent, String fqn, int offset) {
             name = fqn.substring(0, indx);
             props.append(fqn.substring(indx + 1));
         }
-        List<TypeUsage> localResolved = new ArrayList<TypeUsage>();
+        List<TypeUsage> localResolved = new ArrayList<>();
 
         resolveAssignments(parent, name, offset, localResolved, props);
 
-        boolean typeResolved = false;
-        for (TypeUsage type : localResolved) {
-            if (type.isResolved()) {
-                String newObjectName = type.getType();
-                JsObject object = ModelUtils.searchJsObjectByName(parent, newObjectName);
-                if ((object != null) && (object != parent)) {
-                    String partfqn = props.toString();
-                    if (!partfqn.trim().equals("")) {
-                        String[] tokens = partfqn.split("\\.");
-                        for (int i = 0; i < tokens.length; i++) {
-                            object = ModelUtils.searchJsObjectByName(parent, newObjectName);
-                            for (JsObject prop : object.getProperties().values()) {
-                                if ((prop.getName().equals(tokens[i])) && (prop.isDeclared())) {
-                                    if (prop.getAssignmentCount() > 0) {
-                                        for (TypeUsage type1 : prop.getAssignments()) {
-                                            return resolveTypes(object, String.join(".", Arrays.copyOfRange(tokens, i, tokens.length)), offset);
-                                        }
-                                    } else {
-                                        object = prop;
-                                        newObjectName = newObjectName + "." + prop.getName();
-                                        if (i == tokens.length - 1) {
-                                            typeResolved = true;
+        List<TypeUsage> diff = localResolved.stream().filter(type -> !alreadyResolved.contains(type)).collect(Collectors.toList());
+        if (diff.size() > 0) {
+            alreadyResolved.addAll(diff);
+            boolean typeResolved = false;
+            for (TypeUsage type : localResolved) {
+                if (type.isResolved()) {
+                    String newObjectName = type.getType();
+                    JsObject object = ModelUtils.searchJsObjectByName(parent, newObjectName);
+                    if ((object != null) && (object != parent)) {
+                        String partfqn = props.toString();
+                        if (!partfqn.trim().equals("")) {
+                            String[] tokens = partfqn.split("\\.");
+                            for (int i = 0; i < tokens.length; i++) {
+                                object = ModelUtils.searchJsObjectByName(parent, newObjectName);
+                                for (JsObject prop : object.getProperties().values()) {
+                                    if ((prop.getName().equals(tokens[i])) && (prop.isDeclared())) {
+                                        if (prop.getAssignmentCount() > 0) {
+                                            if (invokeCount == MAX_RECURSION_DEEP_RESOLVING_ASSIGNMENTS) {
+                                                LOG.log(Level.WARNING, "StackOverFlowError : {0} : {1}",
+                                                        new Object[]{object.getFullyQualifiedName(),
+                                                            object.getFileObject()});
+                                            }
+                                            return resolveTypes(object, String.join(".", Arrays.copyOfRange(tokens, i, tokens.length)), offset, alreadyResolved, invokeCount);
+                                        } else {
+                                            object = prop;
+                                            newObjectName = newObjectName + "." + prop.getName();
+                                            if (i == tokens.length - 1) {
+                                                typeResolved = true;
+                                            }
+                                            break;
                                         }
-                                        break;
                                     }
                                 }
                             }
-                        }
-                        if (typeResolved) {
-                            return new TypeUsage(newObjectName, type.getOffset(), true);
-                        }
+                            if (typeResolved) {
+                                return new TypeUsage(newObjectName, type.getOffset(), true);
+                            }
 
+                        }
                     }
                 }
             }
@@ -1232,11 +1247,12 @@ private static TypeUsage resolveTypes(JsObject parent, String fqn, int offset) {
 
     private static void resolveAssignments(JsObject jsObject, String fqn, int offset, List<TypeUsage> resolved, StringBuilder nestedProperties) {
 
+        int invokeCount = 0;
         Set<String> alreadyProcessed = new HashSet<String>();
         for (TypeUsage type : resolved) {
             alreadyProcessed.add(type.getType());
         }
-        resolveAssignments(jsObject, fqn, offset, resolved, alreadyProcessed, nestedProperties);
+        resolveAssignments(jsObject, fqn, offset, resolved, alreadyProcessed, nestedProperties, invokeCount);
     }
 
     /**
@@ -1250,8 +1266,9 @@ private static void resolveAssignments(JsObject jsObject, String fqn, int offset
      * @param nestedProperties "." separated nested property names string part
      * of FQN
      */
-    private static void resolveAssignments(JsObject parent, String fqn, int offset, List<TypeUsage> resolved, Set<String> alreadyProcessed, StringBuilder nestedProperties) {
+    private static void resolveAssignments(JsObject parent, String fqn, int offset, List<TypeUsage> resolved, Set<String> alreadyProcessed, StringBuilder nestedProperties, int invokeCount) {
         if (!alreadyProcessed.contains(fqn)) {
+            invokeCount++;
             alreadyProcessed.add(fqn);
             String fqnCorrected = ModelUtils.getFQNFromType(new TypeUsage(fqn, offset, false));
             //resolve the parent object in fqn
@@ -1277,7 +1294,12 @@ private static void resolveAssignments(JsObject parent, String fqn, int offset,
                     }
                     for (TypeUsage type : toProcess) {
                         if (!alreadyProcessed.contains(type.getType())) {
-                            resolveAssignments(parent, type.getType(), type.getOffset(), resolved, alreadyProcessed, nestedProperties);
+                            if (invokeCount == MAX_RECURSION_DEEP_RESOLVING_ASSIGNMENTS) {
+                                LOG.log(Level.WARNING, "StackOverFlowError : {0} : {1}",
+                                        new Object[]{object.getFullyQualifiedName(),
+                                                     object.getFileObject()});
+                            }
+                            resolveAssignments(parent, type.getType(), type.getOffset(), resolved, alreadyProcessed, nestedProperties, invokeCount);
                         }
                     }
                 } else {


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists