This is an automated email from the ASF dual-hosted git repository. rtaneja pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git
The following commit(s) were added to refs/heads/master by this push: new c24241d [NETBEANS-1438] : stackoverflowerror opening .js files (#994) c24241d is described below commit c24241d558a02450c2c5a4b630a1740cbdf94f90 Author: Reema Taneja <32299405+rtane...@users.noreply.github.com> AuthorDate: Fri Nov 2 10:23:08 2018 +0530 [NETBEANS-1438] : stackoverflowerror opening .js files (#994) * [NETBEANS-1438] : stackoverflowerror opening .js files * [NETBEANS-1438] : StackOverFlowError opening .js files * removed redundant code --- .../unit/data/testfiles/coloring/issue233298_3.js | 6 ++ .../editor/navigation/GoToDeclarationTest.java | 4 + .../modules/javascript2/model/api/ModelUtils.java | 88 ++++++++++++++-------- 3 files changed, 65 insertions(+), 33 deletions(-) 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 0000000..89df478 --- /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 d5964d7..c196fce 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 class GoToDeclarationTest extends JsTestBase { 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 fc58224..1882a87 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.Iterator; 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 @@ public class ModelUtils { 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 class ModelUtils { * @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 @@ public class ModelUtils { 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 @@ public class ModelUtils { 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 @@ public class ModelUtils { * @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 @@ public class ModelUtils { } 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 { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists