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/07/04 00:25:32 UTC

[GitHub] junichi11 closed pull request #621: donation2_merge: #233298: fix goto declaration navigation

junichi11 closed pull request #621: donation2_merge: #233298: fix goto declaration navigation
URL: https://github.com/apache/incubator-netbeans/pull/621
 
 
   

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/javascript2.editor/test/unit/data/testfiles/coloring/issue233298.js b/javascript2.editor/test/unit/data/testfiles/coloring/issue233298.js
new file mode 100644
index 0000000000..fde6ade396
--- /dev/null
+++ b/javascript2.editor/test/unit/data/testfiles/coloring/issue233298.js
@@ -0,0 +1,11 @@
+var man1 = {
+    name: "xyz",
+    addr: {
+        doorNo: "10",        
+    }
+};
+
+var address = man1.addr;
+address.doorNo = "11";
+a.b = a.b;
+
diff --git a/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_1.js b/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_1.js
new file mode 100644
index 0000000000..882fe39c99
--- /dev/null
+++ b/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_1.js
@@ -0,0 +1,33 @@
+var man1 = {
+    name: "xyz",
+    addr: {
+        h_addr: {
+            doorNo: "10",
+        }
+    }
+};
+
+
+var man2 = man1;
+var addr1 = man2.addr;
+var addr2 = addr1;
+var add = addr2.h_addr;
+add.doorNo = "11";
+
+
+var company = {
+    name: "CCC",
+    manager: {
+        dept: "something",
+        dtl: man2
+    }
+}
+
+var addr3 = company.manager.dtl.addr.h_addr;
+addr3.doorNo = "50";
+
+var addr4 = company.manager.dtl.addr;
+addr4.h_addr.doorNo = "70";
+
+
+
diff --git a/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_2.js b/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_2.js
new file mode 100644
index 0000000000..d9b0683839
--- /dev/null
+++ b/javascript2.editor/test/unit/data/testfiles/coloring/issue233298_2.js
@@ -0,0 +1,29 @@
+/**
+ * @constructor
+ * @returns {Man}
+ */
+function Man (fName, sName) {
+    var firstName = fName;
+    var secondName = sName;
+
+    this.getFirstName = function () {
+        return firstName;
+    }
+
+    this.getSecondName = function () {
+        return secondName;
+    }
+
+    this.address = {
+        street: "unknown",
+        city: "unknown",
+        zip: "15000"
+    }
+
+}
+
+var petr = new Man("Petr", "Pavel");
+var add = petr.address;
+add.zip = "1234";
+
+
diff --git a/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java b/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java
index e4810b8da8..4de37b38f5 100644
--- a/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java
+++ b/javascript2.editor/test/unit/src/org/netbeans/modules/javascript2/editor/navigation/GoToDeclarationTest.java
@@ -56,6 +56,26 @@ public GoToDeclarationTest(String testName) {
     public void testIssue209941_01() throws Exception {
         checkDeclaration("testfiles/coloring/issue209941.js", "this.globalNot^ify();", "    this.^globalNotify = function() {");
     }
+            
+    public void testIssue233298_0() throws Exception {        
+        checkDeclaration("testfiles/coloring/issue233298.js", "address.door^No", "^doorNo: \"10\"");        
+    }
+        
+    public void testIssue233298_1() throws Exception {        
+        checkDeclaration("testfiles/coloring/issue233298_1.js", "add.door^No", "^doorNo: \"10\"");        
+    }
+    
+    public void testIssue233298_2() throws Exception {        
+        checkDeclaration("testfiles/coloring/issue233298_1.js", "addr3.door^No", "^doorNo: \"10\"");        
+    }
+    
+    public void testIssue233298_3() throws Exception {
+        checkDeclaration("testfiles/coloring/issue233298_2.js", "add.zi^p", "^zip: \"15000\"");        
+    }
+
+    public void testIssue233298_4() throws Exception { 
+        checkDeclaration("testfiles/coloring/issue233298.js", "a.b^", "a.^b");
+    }
     
     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/javascript2.model/src/org/netbeans/modules/javascript2/model/JsObjectImpl.java b/javascript2.model/src/org/netbeans/modules/javascript2/model/JsObjectImpl.java
index d5a8e1db31..ca70d73440 100644
--- a/javascript2.model/src/org/netbeans/modules/javascript2/model/JsObjectImpl.java
+++ b/javascript2.model/src/org/netbeans/modules/javascript2/model/JsObjectImpl.java
@@ -475,12 +475,13 @@ public void resolveTypes(JsDocumentationHolder jsDocHolder) {
                 if (!type.getType().contains(ModelUtils.THIS)) {
                     for (TypeUsage typeHere : resolvedHere) {
                         if (typeHere.getOffset() > 0) {
-                            String rType = typeHere.getType();
-                            if (rType.startsWith(SemiTypeResolverVisitor.ST_EXP)) {
-                                rType = rType.substring(5);
-                                rType = rType.replace(SemiTypeResolverVisitor.ST_PRO, ".");
+                            TypeUsage newType = typeHere;
+                            if (!typeHere.isResolved() && (typeHere.getType().startsWith(SemiTypeResolverVisitor.ST_PRO))) {
+                                newType = ModelUtils.createResolvedType(global, typeHere);
                             }
+                            String rType = ModelUtils.getFQNFromType(newType);
                             JsObject jsObject = ModelUtils.findJsObjectByName(global, rType);
+                            
                             if (jsObject == null && rType.indexOf('.') == -1 && global instanceof DeclarationScope) {
                                 DeclarationScope declarationScope = ModelUtils.getDeclarationScope((DeclarationScope) global, typeHere.getOffset());
                                 jsObject = ModelUtils.getJsObjectByName(declarationScope, rType);
diff --git a/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java b/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java
index ed0c352bfc..9e1ad1f848 100644
--- a/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java
+++ b/javascript2.model/src/org/netbeans/modules/javascript2/model/api/ModelUtils.java
@@ -1186,6 +1186,144 @@ public static boolean hasDeclaredProperty(JsObject jsObject) {
             return Collections.singletonList(type.getType());
         }
     }
+
+    /**
+     * Resolve assignments to return a resolved typeUsage
+     *
+     * @param parent Parent Object
+     * @param typeHere TypeUsage for the assignment
+     * @return
+     */
+    public static TypeUsage createResolvedType(JsObject parent, TypeUsage typeHere) {
+        String fqn = getFQNFromType(typeHere);
+        return resolveTypes(parent, fqn, typeHere.getOffset());
+    }
+
+    /* @return TypeUsage with generated typename string 
+     */
+    private static TypeUsage resolveTypes(JsObject parent, String fqn, int offset) {
+
+        String name = fqn;
+        StringBuilder props = new StringBuilder();
+        int indx = fqn.indexOf(".");
+        if (indx != -1) {
+            name = fqn.substring(0, indx);
+            props.append(fqn.substring(indx + 1));
+        }
+        List<TypeUsage> localResolved = new ArrayList<TypeUsage>();
+
+        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;
+                                        }
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        if (typeResolved) {
+                            return new TypeUsage(newObjectName, type.getOffset(), true);
+                        }
+
+                    }
+                }
+            }
+        }
+        return new TypeUsage(fqn, offset, false);
+    }
+
+    private static void resolveAssignments(JsObject jsObject, String fqn, int offset, List<TypeUsage> resolved, StringBuilder nestedProperties) {
+
+        Set<String> alreadyProcessed = new HashSet<String>();
+        for (TypeUsage type : resolved) {
+            alreadyProcessed.add(type.getType());
+        }
+        resolveAssignments(jsObject, fqn, offset, resolved, alreadyProcessed, nestedProperties);
+    }
+
+    /**
+     * Resolves assignments for the top level object in a given fqn
+     *
+     * @param parent parent JsObject
+     * @param fqn assignment Type name string
+     * @param offset assignment Type offset
+     * @param resolved list of resolved TypeUsages
+     * @param alreadyProcessed List of FQNs already resolved
+     * @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) {
+        if (!alreadyProcessed.contains(fqn)) {
+            alreadyProcessed.add(fqn);
+            String fqnCorrected = ModelUtils.getFQNFromType(new TypeUsage(fqn, offset, false));
+            //resolve the parent object in fqn
+            int index = fqnCorrected.indexOf(".");//NOI18N
+            if (index != -1) {
+                //save the remaining fqn part to locate in object properties later
+                nestedProperties.insert(0, fqnCorrected.substring(index + 1) + ".");
+                fqnCorrected = fqnCorrected.substring(0, index);
+            }
+            if (!fqnCorrected.startsWith("@")) {
+                List<TypeUsage> toProcess = new ArrayList<TypeUsage>();
+                JsObject object = ModelUtils.searchJsObjectByName(parent, fqnCorrected);
+
+                if ((object != null) && (((JsObjectImpl) object).getAssignmentCount() > 0)) {
+                    for (TypeUsage type : ((JsObjectImpl) object).getAssignments()) {
+                        if (!type.isResolved()) {
+                            for (TypeUsage resolvedType : resolveTypeFromSemiType(object, type)) {
+                                toProcess.add(resolvedType);
+                            }
+                        } else {
+                            toProcess.add(type);
+                        }
+                    }
+                    for (TypeUsage type : toProcess) {
+                        if (!alreadyProcessed.contains(type.getType())) {
+                            resolveAssignments(parent, type.getType(), type.getOffset(), resolved, alreadyProcessed, nestedProperties);
+                        }
+                    }
+                } else {
+                    ModelUtils.addUniqueType(resolved, new TypeUsage(fqnCorrected, offset, true));
+                }
+            } else {
+                ModelUtils.addUniqueType(resolved, new TypeUsage(fqnCorrected, offset, false));
+            }
+        }
+    }
+
+    private static JsObject searchJsObjectByName(JsObject parent, String fqn) {
+        JsObject object = ModelUtils.findJsObjectByName(parent, fqn);
+        if (object == null) {
+            if (!isGlobal(parent)) {
+                if (parent.getParent() != null) {
+                    parent = parent.getParent();
+                    return searchJsObjectByName(parent, fqn);
+                }
+            }
+        }
+        return object;
+    }
     
     public static Collection<TypeUsage> resolveTypes(Collection<? extends TypeUsage> unresolved, Model model, Index jsIndex, boolean includeAllPossible) {
         //assert !SwingUtilities.isEventDispatchThread() : "Type resolution may block AWT due to index search";


 

----------------------------------------------------------------
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