use of org.ballerinalang.plugins.idea.psi.ParameterNode in project ballerina by ballerina-lang.
the class BallerinaPsiImplUtil method findStructDefinition.
/**
* Resolves the corresponding struct definition of the provided identifier node if possible.
* Eg:
* <pre>
* function main (string[] args) {
* var person = getData();
* var person2 = person;
* var person3 = person2;
*
* system:println(person3.<caret>);
* }
*
* function getData () (Person) {
* Person person = {name:"Shan", age:26};
* return person;
* }
*
* struct Person {
* string name;
* int age;
* }
* </pre>
* <p>
* From the above caret position, we should be able to get the type of the 'person3'. So we resolve recursively
* until we find the struct definition. If the RHS has a variable, we resolve the definition of the variable and
* call this method again. So in the first call of this function, 'resolvedElement' will be the
* definition of 'person3'. Next, the definition of 'person2' and definition of 'person' after that. At that point,
* we find a function invocation in the RHS. So we get the type from that.
*
* @param resolvedElement element which was resolved from the variable reference
* @return corresponding {@link StructDefinitionNode} if the structName can be resolved, {@code null} otherwise.
*/
@Nullable
public static StructDefinitionNode findStructDefinition(@NotNull IdentifierPSINode resolvedElement) {
// Since this method might get called recursively, it is better to check whether the process is cancelled in the
// beginning.
ProgressManager.checkCanceled();
// Get the assignment statement parent node.
AssignmentStatementNode assignmentStatementNode = PsiTreeUtil.getParentOfType(resolvedElement, AssignmentStatementNode.class);
// count as a definition and does not resolve to it.
if (assignmentStatementNode != null) {
return getStructDefinition(assignmentStatementNode, resolvedElement);
}
// If the resolved element is not in an AssignmentStatement, we check for VariableDefinition parent node.
// If there is a VariableDefinition parent node, finding the type is quite straight forward.
VariableDefinitionNode variableDefinitionNode = PsiTreeUtil.getParentOfType(resolvedElement, VariableDefinitionNode.class);
if (variableDefinitionNode != null) {
return resolveStructFromDefinitionNode(variableDefinitionNode);
}
ParameterNode parameterNode = PsiTreeUtil.getParentOfType(resolvedElement, ParameterNode.class);
if (parameterNode != null) {
return resolveStructFromDefinitionNode(parameterNode);
}
return null;
}
use of org.ballerinalang.plugins.idea.psi.ParameterNode in project ballerina by ballerina-lang.
the class BallerinaPsiImplUtil method getType.
/**
* Returns the type of the provided identifier.
*
* @param identifier an identifier
* @return the type of the identifier. This can be one of {@link ValueTypeNameNode} (for value types like string),
* {@link BuiltInReferenceTypeNameNode} (for reference types like json) or {@link TypeNameNode} (for arrays).
*/
@Nullable
public static PsiElement getType(@NotNull IdentifierPSINode identifier) {
PsiElement parent = identifier.getParent();
// In case of lambda functions or functions attached to types.
if (parent instanceof FunctionDefinitionNode) {
CodeBlockParameterNode codeBlockParameterNode = PsiTreeUtil.getChildOfType(parent, CodeBlockParameterNode.class);
if (codeBlockParameterNode != null) {
TypeNameNode typeNameNode = PsiTreeUtil.getChildOfType(codeBlockParameterNode, TypeNameNode.class);
if (typeNameNode != null) {
return typeNameNode.getFirstChild();
}
}
}
PsiReference reference = identifier.findReferenceAt(0);
if (reference != null) {
// Todo - Do we need to consider this situation?
}
VariableDefinitionNode variableDefinitionNode = PsiTreeUtil.getParentOfType(identifier, VariableDefinitionNode.class);
if (variableDefinitionNode != null) {
PsiElement typeNode = getType(variableDefinitionNode);
if (typeNode != null) {
return typeNode;
}
}
AssignmentStatementNode assignmentStatementNode = PsiTreeUtil.getParentOfType(identifier, AssignmentStatementNode.class);
if (assignmentStatementNode != null) {
PsiElement typeNode = getType(assignmentStatementNode, identifier);
if (typeNode != null) {
return typeNode;
}
}
ParameterNode parameterNode = PsiTreeUtil.getParentOfType(identifier, ParameterNode.class);
if (parameterNode != null) {
PsiElement typeNode = getType(parameterNode);
if (typeNode != null) {
return typeNode;
}
}
FieldDefinitionNode fieldDefinitionNode = PsiTreeUtil.getParentOfType(identifier, FieldDefinitionNode.class);
if (fieldDefinitionNode != null) {
PsiElement typeNode = getType(fieldDefinitionNode);
if (typeNode != null) {
return typeNode;
}
}
return null;
}
use of org.ballerinalang.plugins.idea.psi.ParameterNode in project ballerina by ballerina-lang.
the class BallerinaPsiImplUtil method getAllParametersInScope.
@NotNull
private static List<IdentifierPSINode> getAllParametersInScope(@NotNull ScopeNode scope, int caretOffset) {
List<IdentifierPSINode> results = new LinkedList<>();
Collection<ParameterNode> parameterNodes = PsiTreeUtil.findChildrenOfType(scope, ParameterNode.class);
for (ParameterNode parameter : parameterNodes) {
ScopeNode parentScope = PsiTreeUtil.getParentOfType(parameter, ScopeNode.class);
if (!scope.equals(parentScope)) {
continue;
}
PsiElement identifier = parameter.getNameIdentifier();
if (identifier != null && identifier instanceof IdentifierPSINode) {
results.add(((IdentifierPSINode) identifier));
}
}
Collection<CodeBlockParameterNode> codeBlockParameterNodes = PsiTreeUtil.findChildrenOfType(scope, CodeBlockParameterNode.class);
for (CodeBlockParameterNode parameter : codeBlockParameterNodes) {
PsiElement elementAtCaret = scope.getContainingFile().findElementAt(caretOffset);
if (elementAtCaret == null) {
return results;
}
if (parameter.getTextRange().getEndOffset() >= caretOffset) {
return results;
}
ScopeNode closestScope = PsiTreeUtil.getParentOfType(parameter, ScopeNode.class);
if (closestScope == null || !closestScope.equals(scope)) {
continue;
}
PsiElement identifier = parameter.getNameIdentifier();
if (identifier != null && identifier instanceof IdentifierPSINode) {
results.add(((IdentifierPSINode) identifier));
}
}
return results;
}
use of org.ballerinalang.plugins.idea.psi.ParameterNode in project ballerina by ballerina-lang.
the class BallerinaParameterInfoHandler method getParameterPresentations.
/**
* Creates a list of parameter presentations.
*
* @param node parameterListNode which contains the parameters
* @return list of parameter presentations
*/
public static List<String> getParameterPresentations(ParameterListNode node) {
List<String> params = new LinkedList<>();
if (node == null) {
return params;
}
// Get parameter nodes.
Collection<ParameterNode> parameterNodes = PsiTreeUtil.getChildrenOfTypeAsList(node, ParameterNode.class);
for (ParameterNode parameterNode : parameterNodes) {
// Parameters might have spaces in between. So we need to remove them as well.
params.add(formatParameter(parameterNode.getText()));
}
return params;
}
use of org.ballerinalang.plugins.idea.psi.ParameterNode in project ballerina by ballerina-lang.
the class BallerinaDocumentationProvider method getReturnTypes.
/**
* Returns the return types of the given definition node. This return types are later used to generate the
* signature.
*
* @param definitionNode definition node which we want to get the return types
* @return list of return type strings.
*/
private static List<String> getReturnTypes(PsiElement definitionNode) {
List<String> results = new LinkedList<>();
// Parameters are in the ReturnParameterNode. So we first get the ReturnParameterNode from the definition
// node.
ReturnParameterNode node = PsiTreeUtil.findChildOfType(definitionNode, ReturnParameterNode.class);
if (node == null) {
return results;
}
// But there can be two possible scenarios. The actual return types can be in either ParameterTypeNameList or
// ParameterListNode. This is because return types can be named parameters. In that case, ParameterListNode is
// available.
// First we check for ParameterTypeNameList.
ParameterTypeNameList parameterTypeNameList = PsiTreeUtil.findChildOfType(node, ParameterTypeNameList.class);
// If it is available, that means the return types are not named parameters.
if (parameterTypeNameList != null) {
// Each parameter will be of type TypeNameNode. So we get all return types.
Collection<ParameterTypeName> parameterTypeNames = PsiTreeUtil.getChildrenOfTypeAsList(parameterTypeNameList, ParameterTypeName.class);
// Add each TypeNameNode to the result list.
parameterTypeNames.forEach(parameterTypeName -> {
TypeNameNode typeNameNode = PsiTreeUtil.getChildOfType(parameterTypeName, TypeNameNode.class);
if (typeNameNode != null) {
results.add(BallerinaParameterInfoHandler.formatParameter(typeNameNode.getText()));
}
});
// Return the results.
return results;
}
// If there is no return type node, we check for ParameterListNode.
ParameterListNode parameterListNode = PsiTreeUtil.findChildOfType(node, ParameterListNode.class);
if (parameterListNode != null) {
// Actual parameters are in ParameterNodes.
Collection<ParameterNode> parameterNodes = PsiTreeUtil.findChildrenOfType(parameterListNode, ParameterNode.class);
// Add each ParameterNode to the result list.
parameterNodes.forEach(parameterNode -> results.add(BallerinaParameterInfoHandler.formatParameter(parameterNode.getText())));
// Return the results.
return results;
}
// Return empty list.
return results;
}
Aggregations