Skip to content
This repository has been archived by the owner on Oct 5, 2021. It is now read-only.

Commit

Permalink
Merge pull request #740 from Shan1024/fix-multi-level-function-invoca…
Browse files Browse the repository at this point in the history
…tion-issue

Fix multi level function invocation issue
  • Loading branch information
Shan Mahanama authored Dec 14, 2017
2 parents 18a6352 + 6a004f0 commit 672335d
Show file tree
Hide file tree
Showing 76 changed files with 2,565 additions and 1,177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
import org.ballerinalang.plugins.idea.psi.ImportDeclarationNode;
import org.ballerinalang.plugins.idea.psi.NamespaceDeclarationNode;
import org.ballerinalang.plugins.idea.psi.PackageNameNode;
import org.ballerinalang.plugins.idea.psi.ReferenceTypeNameNode;
import org.ballerinalang.plugins.idea.psi.ReturnParametersNode;
import org.ballerinalang.plugins.idea.psi.ReturnStatementNode;
import org.ballerinalang.plugins.idea.psi.SimpleLiteralNode;
Expand Down Expand Up @@ -382,6 +383,8 @@ public PsiElement createElement(ASTNode node) {
return new EnumFieldNode(node);
case BallerinaParser.RULE_builtInReferenceTypeName:
return new BuiltInReferenceTypeNameNode(node);
case BallerinaParser.RULE_referenceTypeName:
return new ReferenceTypeNameNode(node);
case BallerinaParser.RULE_functionTypeName:
return new FunctionTypeNameNode(node);
case BallerinaParser.RULE_lambdaFunction:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

import static org.ballerinalang.plugins.idea.grammar.BallerinaParser.*;

public class IdentifierPSINode extends ANTLRPsiLeafNode implements PsiNamedElement, PsiNameIdentifierOwner {
Expand Down Expand Up @@ -302,6 +304,15 @@ private PsiReference suggestReferenceTypeForInvocation() {
}
reference = identifier.findReferenceAt(identifier.getTextLength());
}
FunctionInvocationNode functionInvocationNode = PsiTreeUtil.getChildOfType(prevSibling,
FunctionInvocationNode.class);
if (functionInvocationNode != null) {
FunctionReferenceNode functionReferenceNode = PsiTreeUtil.getChildOfType(functionInvocationNode,
FunctionReferenceNode.class);
if (functionReferenceNode != null) {
return new NameReference(this);
}
}
if (reference == null) {
reference = prevSibling.findReferenceAt(prevSibling.getTextLength());
}
Expand All @@ -317,8 +328,8 @@ private PsiReference suggestReferenceTypeForInvocation() {
}
PsiElement definitionNode = resolvedElement.getParent();
if (definitionNode instanceof VariableDefinitionNode) {
ConnectorDefinitionNode connectorDefinitionNode = BallerinaPsiImplUtil
.resolveConnectorFromVariableDefinitionNode((definitionNode));
ConnectorDefinitionNode connectorDefinitionNode =
BallerinaPsiImplUtil.resolveConnectorFromVariableDefinitionNode((definitionNode));
if (connectorDefinitionNode != null) {
return new ActionInvocationReference(this);
}
Expand All @@ -328,6 +339,8 @@ private PsiReference suggestReferenceTypeForInvocation() {
if (connectorReferenceNode != null) {
return new ActionInvocationReference(this);
}
} else if (definitionNode instanceof FunctionDefinitionNode) {
return new NameReference(this);
}
reference = checkAndSuggestReferenceAfterDot();
if (reference != null) {
Expand Down Expand Up @@ -373,14 +386,24 @@ private PsiReference checkAndSuggestReferenceAfterDot() {
if (resolvedElement == null) {
return null;
}
// Get the return type of the function definition.
PsiElement parent = resolvedElement.getParent();
if (parent instanceof FunctionDefinitionNode) {
List<TypeNameNode> returnTypes = BallerinaPsiImplUtil.getReturnTypes(((FunctionDefinitionNode) parent));
if (returnTypes.size() == 1) {
return new TypeReference(this, returnTypes.get(0));
}
}

if (resolvedElement.getParent() instanceof EndpointDeclarationNode) {
return new ActionInvocationReference(this);
}
if (resolvedElement.getParent() instanceof EnumDefinitionNode) {
return new EnumFieldReference(this);
}
PsiElement type = BallerinaPsiImplUtil.getType(((IdentifierPSINode) resolvedElement));
if (type == null || (!(type instanceof BuiltInReferenceTypeNameNode) && !(type instanceof ValueTypeNameNode))) {
if (type == null || (!(type instanceof BuiltInReferenceTypeNameNode) && !(type instanceof ReferenceTypeNameNode)
&& !(type instanceof ValueTypeNameNode))) {
return null;
}
return new TypeReference(this, type);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.ballerinalang.plugins.idea.psi;

import com.intellij.lang.ASTNode;
import org.antlr.jetbrains.adaptor.psi.ANTLRPsiNode;
import org.jetbrains.annotations.NotNull;

public class ReferenceTypeNameNode extends ANTLRPsiNode {

public ReferenceTypeNameNode(@NotNull ASTNode node) {
super(node);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -196,7 +197,9 @@ public Object[] getVariants() {
BallerinaPsiImplUtil.getReturnTypes(((FunctionDefinitionNode) parent));
if (returnTypes.size() == 1) {
TypeNameNode typeNameNode = returnTypes.get(0);
reference = typeNameNode.findReferenceAt(typeNameNode.getTextLength());
List<LookupElement> functions =
Arrays.asList((LookupElement[]) TypeReference.getVariants(typeNameNode));
return functions.toArray(new LookupElement[functions.size()]);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ public TypeReference(@NotNull IdentifierPSINode element, PsiElement typeNameNode
@Nullable
@Override
public PsiElement resolve() {
IdentifierPSINode identifier = getElement();
return resolve(typeNameNode, getElement());
}

@Nullable
public static PsiElement resolve(PsiElement typeNameNode, IdentifierPSINode identifier) {
String valueTypeName = typeNameNode.getText();
Project project = typeNameNode.getProject();
PsiFile psiFile = BallerinaPsiImplUtil.findPsiFileInSDK(project, typeNameNode,
Expand All @@ -63,6 +67,11 @@ public PsiElement resolve() {
@NotNull
@Override
public Object[] getVariants() {
return getVariants(typeNameNode);
}

@NotNull
public static Object[] getVariants(PsiElement typeNameNode) {
String valueTypeName = typeNameNode.getText();
Project project = typeNameNode.getProject();
PsiFile psiFile = BallerinaPsiImplUtil.findPsiFileInSDK(project, typeNameNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private static DefaultLightProjectDescriptor createMockProjectDescriptor() {
@NotNull
@Override
public Sdk getSdk() {
return createMockSdk("0.88");
return createMockSdk("0.95.4");
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ public void testImportFromSDKFirstLevel() {
}

public void testImportFromSDKSecondLevel() {
doTest("import ballerina.<caret>", "data", "doc", "lang", "net", "utils");
doTest("import ballerina.<caret>", "builtin", "caching", "config", "data", "file", "io", "log", "math",
"net", "os", "runtime", "security", "task", "user", "util");
}

public void testImportFromSDKThirdLevel() {
doTest("import ballerina.lang.<caret>", "arrays", "blobs", "datatables", "errors", "files", "jsons", "maps",
"messages", "strings", "system", "type", "xmls");
doTest("import ballerina.net.<caret>", "http", "uri", "ws");
}

public void testImportFromSDKAfterPackage() {
Expand All @@ -71,17 +71,40 @@ public void testImportFromSDKBetweenImports() {
}

public void testPackageInvocationAutoCompletion() {
doCheckResult("test.bal", "import ballerina.lang.system; function test() {sys<caret>}",
"import ballerina.lang.system; function test() {system:}", null);
doCheckResult("test.bal", "import ballerina.net.http; function test() {ht<caret>}",
"import ballerina.net.http; function test() {http:}", null);
}

public void testFunctionInvocationFromAPackage() {
doTest("import ballerina.lang.system; function test() {system:<caret>}", "currentTimeMillis", "epochTime",
"getDateFormat", "getEnv", "log", "nanoTime", "print", "println");
doTest("import ballerina.net.uri; function test() {uri:<caret>}", "encode");
}

public void testFunctionInvocationFromAPackageAutoCompletion() {
doCheckResult("test.bal", "import ballerina.lang.system; function test() {system:nano<caret>}",
"import ballerina.lang.system; function test() {system:nanoTime()}", null);
doCheckResult("test.bal", "import ballerina.net.uri; function test() {uri:en<caret>}",
"import ballerina.net.uri; function test() {uri:encode()}", null);
}

public void testMultiLevelFunctionInvocation1() {
doTest("function test() {string s =\"\"; \n string s2 = s.<caret>}", "contains", "equalsIgnoreCase",
"hasPrefix", "hasSuffix", "indexOf", "lastIndexOf", "length", "replace", "replaceAll",
"replaceFirst", "split", "subString", "toBlob", "toLowerCase", "toUpperCase", "trim", "unescape");
}

public void testMultiLevelFunctionInvocation2() {
doTest("function test() {string s =\"\"; \n string s2 = s.toUpperCase().<caret>}", "contains",
"equalsIgnoreCase", "hasPrefix", "hasSuffix", "indexOf", "lastIndexOf", "length", "replace",
"replaceAll", "replaceFirst", "split", "subString", "toBlob", "toLowerCase", "toUpperCase", "trim",
"unescape");
}

public void testMultiLevelFunctionInvocation3() {
doTest("function test() {string s =\"\"; \n string s2 = s.toUpperCase().toLowerCase().<caret>}", "contains",
"equalsIgnoreCase", "hasPrefix", "hasSuffix", "indexOf", "lastIndexOf", "length", "replace",
"replaceAll", "replaceFirst", "split", "subString", "toBlob", "toLowerCase", "toUpperCase", "trim",
"unescape");
}

public void testMultiLevelFunctionInvocation4() {
doTest("function test() {string s =\"\"; \n string s2 = s.toUpperCase().toBlob().<caret>}", "toString");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,28 +111,24 @@ public void testSDKFunctionWithNoParam() {
doTest(NO_PARAMETER);
}

public void testSDKConnectorWithSingleParam() {
doTest("<html><b>string serviceUri</b></html>");
}

public void testSDKActionWithMultipleParam() {
doTest("<html><b>ClientConnector c</b>, string path, message m</html>");
doTest("<html><b>string serviceUri</b>, Options connectorOptions</html>");
}

public void testSDKActionWithMultipleParamSecondElement() {
doTest(1, "<html>ClientConnector c, <b>string path</b>, message m</html>");
doTest(1, "<html>string serviceUri, <b>Options connectorOptions</b></html>");
}

public void testSDKFunctionWithSingleParam() {
doTest("<html><b>any a</b></html>");
doTest("<html><b>string msg</b></html>");
}

public void testSDKFunctionWithMultipleParam() {
doTest("<html><b>int logLevel</b>, any value</html>");
doTest("<html><b>string name</b>, string value</html>");
}

public void testSDKFunctionWithMultipleParamSecondElement() {
doTest(1, "<html>int logLevel, <b>any value</b></html>");
doTest(1, "<html>string name, <b>string value</b></html>");
}

private void doTest(@NotNull String expectedPresentation) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ballerina.net.http;

function main (string[] args) {
http:ClientConnector con = create http:ClientConnector("http://localhost:8080");
con.get(<caret>)
endpoint<http:HttpClient> httpEndpoint {
create http:HttpClient(<caret>);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ballerina.net.http;

function main (string[] args) {
http:ClientConnector con = create http:ClientConnector("http://localhost:8080");
con.get("",<caret>)
endpoint<http:HttpClient> httpEndpoint {
create http:HttpClient("http://test.com", c<caret>);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ballerina.lang.system;
import ballerina.runtime;

function main (string[] args) {
system:log(<caret>)
runtime:setProperty(<caret>)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ballerina.lang.system;
import ballerina.runtime;

function main (string[] args) {
system:log(1,<caret>)
runtime:setProperty("hello", <caret>)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ballerina.lang.system;
import ballerina.os;

function main (string[] args) {
system:epochTime(<caret>)
os:getName(<caret>)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ballerina.lang.system;
import ballerina.log;

function main (string[] args) {
system:println(<caret>)
log:printDebug(<caret>)
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 672335d

Please sign in to comment.