use of org.ballerinalang.plugins.idea.psi.ActionDefinitionNode in project ballerina by ballerina-lang.
the class BallerinaPsiImplUtil method getStructDefinition.
@Nullable
public static StructDefinitionNode getStructDefinition(@NotNull AssignmentStatementNode assignmentStatementNode, @NotNull IdentifierPSINode structReferenceNode, @NotNull PsiElement definitionNode) {
// Now we need to know the index of the provided struct reference node in the assignment statement node.
int index = getVariableIndexFromVarAssignment(assignmentStatementNode, structReferenceNode);
if (index < 0) {
return null;
}
// Now we get all of the return types from the function.
List<TypeNameNode> returnTypes = new LinkedList<>();
if (definitionNode instanceof FunctionDefinitionNode) {
returnTypes = getReturnTypes(((FunctionDefinitionNode) definitionNode));
}
if (definitionNode instanceof ActionDefinitionNode) {
returnTypes = getReturnTypes(((ActionDefinitionNode) definitionNode));
}
// at least 1, etc.
if (returnTypes.size() <= index) {
return null;
}
// Get the corresponding return type.
PsiElement elementType = returnTypes.get(index);
// If this is a struct, we need to resolve it to the definition.
PsiReference referenceAtElementType = elementType.findReferenceAt(elementType.getTextLength());
if (referenceAtElementType == null) {
return null;
}
PsiElement resolvedIdentifier = referenceAtElementType.resolve();
if (resolvedIdentifier != null) {
// If we can resolve it to a definition, parent should be a struct definition node.
PsiElement structDefinition = resolvedIdentifier.getParent();
if (structDefinition instanceof StructDefinitionNode) {
return (StructDefinitionNode) structDefinition;
}
}
return null;
}
use of org.ballerinalang.plugins.idea.psi.ActionDefinitionNode in project ballerina by ballerina-lang.
the class BallerinaPsiImplUtil method getStructDefinition.
/**
* Finds a {@link StructDefinitionNode} which corresponds to the provided {@link VariableReferenceNode}.
*
* @param variableReferenceNode an variable reference node in the assignment statement node
* @param assignmentStatementNode an assignment statement node
* @param structReferenceNode an identifier which is a var variable in the assignment node
* @return
*/
private static StructDefinitionNode getStructDefinition(@NotNull VariableReferenceNode variableReferenceNode, @NotNull AssignmentStatementNode assignmentStatementNode, @NotNull IdentifierPSINode structReferenceNode) {
InvocationNode invocationNode = PsiTreeUtil.getChildOfType(variableReferenceNode, InvocationNode.class);
if (invocationNode != null) {
AnyIdentifierNameNode anyIdentifierNameNode = PsiTreeUtil.getChildOfType(invocationNode, AnyIdentifierNameNode.class);
if (anyIdentifierNameNode != null) {
IdentifierPSINode identifier = PsiTreeUtil.getChildOfType(anyIdentifierNameNode, IdentifierPSINode.class);
if (identifier != null) {
PsiReference reference = identifier.findReferenceAt(identifier.getTextLength());
if (reference == null) {
return null;
}
PsiElement resolvedElement = reference.resolve();
if (resolvedElement == null) {
return null;
}
// Check whether the resolved element's parent is a connector definition.
PsiElement definitionNode = resolvedElement.getParent();
if (!(definitionNode instanceof ActionDefinitionNode)) {
return null;
}
return getStructDefinition(assignmentStatementNode, structReferenceNode, definitionNode);
}
}
}
// Get the first child.
PsiElement node = variableReferenceNode.getFirstChild();
// If te first child is a VariableReferenceNode, it can be a function invocation.
if (node instanceof VariableReferenceNode) {
// Check whether the node is a function invocation.
boolean isFunctionInvocation = isFunctionInvocation((VariableReferenceNode) node);
if (isFunctionInvocation) {
// If it is a function invocation, the first child node will contain the function name.
PsiElement functionName = node.getFirstChild();
// We need to resolve the function name to the corresponding function definition.
PsiReference reference = functionName.findReferenceAt(functionName.getTextLength());
if (reference == null) {
return null;
}
PsiElement resolvedFunctionIdentifier = reference.resolve();
if (resolvedFunctionIdentifier == null) {
return null;
}
// Check whether the resolved element's parent is a function definition.
PsiElement definitionNode = resolvedFunctionIdentifier.getParent();
if (!(definitionNode instanceof FunctionDefinitionNode)) {
return null;
}
return getStructDefinition(assignmentStatementNode, structReferenceNode, definitionNode);
}
} else if (node instanceof NameReferenceNode) {
// If the node is a NameReferenceNode, that means RHS contains a variable.
PsiReference reference = node.findReferenceAt(node.getTextLength());
if (reference == null) {
return null;
}
// We resolve that variable to the definition.
PsiElement resolvedDefinition = reference.resolve();
if (resolvedDefinition == null || !(resolvedDefinition instanceof IdentifierPSINode)) {
return null;
}
// Then recursively call the findStructDefinition method to get the correct definition.
return findStructDefinition((IdentifierPSINode) resolvedDefinition);
} else if (node instanceof FunctionInvocationNode) {
FunctionReferenceNode functionReferenceNode = PsiTreeUtil.getChildOfType(node, FunctionReferenceNode.class);
if (functionReferenceNode == null) {
return null;
}
PsiReference reference = functionReferenceNode.findReferenceAt(functionReferenceNode.getTextLength());
if (reference == null) {
return null;
}
PsiElement resolvedDefinition = reference.resolve();
if (resolvedDefinition == null || !(resolvedDefinition instanceof IdentifierPSINode)) {
return null;
}
PsiElement definitionNode = resolvedDefinition.getParent();
if (!(definitionNode instanceof FunctionDefinitionNode)) {
return null;
}
return getStructDefinition(assignmentStatementNode, structReferenceNode, definitionNode);
}
return null;
}
use of org.ballerinalang.plugins.idea.psi.ActionDefinitionNode in project ballerina by ballerina-lang.
the class BallerinaFoldingBuilder method buildConnectorFoldRegions.
private void buildConnectorFoldRegions(@NotNull List<FoldingDescriptor> descriptors, @NotNull PsiElement root) {
// Get all connectors.
Collection<ConnectorDefinitionNode> connectorNodes = PsiTreeUtil.findChildrenOfType(root, ConnectorDefinitionNode.class);
for (ConnectorDefinitionNode connectorNode : connectorNodes) {
// Get the connector body. This is used to calculate the start offset.
ConnectorBodyNode connectorBodyNode = PsiTreeUtil.getChildOfType(connectorNode, ConnectorBodyNode.class);
if (connectorBodyNode == null) {
continue;
}
// Add folding descriptor.
addFoldingDescriptor(descriptors, connectorNode, connectorBodyNode);
// We need to add folding support to actions as well. So get all actions in the connector.
Collection<ActionDefinitionNode> actionDefinitionNodes = PsiTreeUtil.findChildrenOfType(root, ActionDefinitionNode.class);
for (ActionDefinitionNode actionDefinitionNode : actionDefinitionNodes) {
// Get the action body. This is used to calculate the start offset.
CallableUnitBodyNode callableUnitBodyNode = PsiTreeUtil.getChildOfType(actionDefinitionNode, CallableUnitBodyNode.class);
if (callableUnitBodyNode == null) {
continue;
}
// Add folding descriptor.
addFoldingDescriptor(descriptors, actionDefinitionNode, callableUnitBodyNode);
}
}
}
use of org.ballerinalang.plugins.idea.psi.ActionDefinitionNode in project ballerina by ballerina-lang.
the class BallerinaDocumentationProvider method getSignature.
@NotNull
private static String getSignature(PsiElement element) {
if (element == null) {
return "";
}
StringBuilder stringBuilder = new StringBuilder();
// element will be an identifier. So we need to get the parent of the element to identify the type to
// generate the signature.
PsiElement parent = element.getParent();
// Generate the signature according to the parent type.
if (parent instanceof FunctionDefinitionNode) {
// Add the function signature.
stringBuilder.append("function ");
stringBuilder.append(element.getText());
// Get parameters.
String params = getParameterString(parent, false);
// Add parameters.
stringBuilder.append("(");
stringBuilder.append(params);
stringBuilder.append(")");
// Get return types. These can be either return types or return parameters.
List<String> returnParamsList = getReturnTypes(parent);
String returnParams = StringUtil.join(returnParamsList, ", ");
if (!returnParams.isEmpty()) {
// Add return types/parameters.
stringBuilder.append("(");
stringBuilder.append(returnParams);
stringBuilder.append(")");
}
} else if (parent instanceof ActionDefinitionNode || parent instanceof AnyIdentifierNameNode) {
// Add the action signature.
stringBuilder.append("action ");
stringBuilder.append(element.getText());
// Get parameters.
String params = getParameterString(parent, false);
// Add parameters.
stringBuilder.append("(");
stringBuilder.append(params);
stringBuilder.append(")");
// Get return types/parameters.
List<String> returnParamsList = getReturnTypes(parent);
String returnParams = StringUtil.join(returnParamsList, ", ");
if (!returnParams.isEmpty()) {
// Add return types/parameters.
stringBuilder.append("(");
stringBuilder.append(returnParams);
stringBuilder.append(")");
}
} else if (parent instanceof ConnectorDefinitionNode) {
// Add the connector signature.
stringBuilder.append("connector ");
stringBuilder.append(element.getText());
// Get parameters.
String params = getParameterString(parent, false);
// Add parameters.
stringBuilder.append("(");
stringBuilder.append(params);
stringBuilder.append(")");
} else if (parent instanceof StructDefinitionNode) {
// Add the function signature.
stringBuilder.append("struct ");
stringBuilder.append(element.getText());
stringBuilder.append(" { }");
} else if (parent instanceof ConstantDefinitionNode) {
// Add the function signature.
stringBuilder.append(parent.getText());
}
// If the doc is available, add package to the top.
if (!stringBuilder.toString().isEmpty()) {
// Add the containing package to the quick doc if there is any.
PsiElement packagePathNode = getContainingPackage(element);
if (packagePathNode != null) {
stringBuilder.insert(0, packagePathNode.getText() + "<br><br>");
}
}
// Return the signature.
return stringBuilder.toString();
}
use of org.ballerinalang.plugins.idea.psi.ActionDefinitionNode in project ballerina by ballerina-lang.
the class BallerinaStructureViewElement method getChildren.
@NotNull
@Override
public TreeElement[] getChildren() {
// The element can be one of BallerinaFile, ConnectorDefinitionNode instance.
if (element instanceof BallerinaFile) {
List<TreeElement> treeElements = new ArrayList<>();
// Add services.
Collection<ServiceDefinitionNode> services = PsiTreeUtil.findChildrenOfType(element, ServiceDefinitionNode.class);
for (PsiElement service : services) {
// In here, instead of using the service, we use service.getParent(). This is done because we
// want to show resources under a service node. This is how the sub nodes can be added.
treeElements.add(new BallerinaStructureViewElement(service));
}
// Add functions.
Collection<FunctionDefinitionNode> functions = PsiTreeUtil.findChildrenOfType(element, FunctionDefinitionNode.class);
for (PsiElement function : functions) {
treeElements.add(new BallerinaStructureViewElement(function));
}
// Add connectors.
Collection<ConnectorDefinitionNode> connectors = PsiTreeUtil.findChildrenOfType(element, ConnectorDefinitionNode.class);
for (PsiElement connector : connectors) {
// In here, instead of using the connector, we use connector.getParent(). This is done because we
// want to show actions under a connector node. This is how the sub nodes can be added.
treeElements.add(new BallerinaStructureViewElement(connector));
}
// Add annotations.
Collection<AnnotationDefinitionNode> annotations = PsiTreeUtil.findChildrenOfType(element, AnnotationDefinitionNode.class);
for (PsiElement annotation : annotations) {
treeElements.add(new BallerinaStructureViewElement(annotation));
}
// Add structs
Collection<StructDefinitionNode> structs = PsiTreeUtil.findChildrenOfType(element, StructDefinitionNode.class);
for (PsiElement struct : structs) {
treeElements.add(new BallerinaStructureViewElement(struct));
}
// Convert the list to an array and return.
return treeElements.toArray(new TreeElement[treeElements.size()]);
} else if (element instanceof ConnectorDefinitionNode) {
// If the element is a ConnectorDefinitionNode instance, we get all actions.
List<TreeElement> treeElements = new ArrayList<>();
// Add actions.
Collection<ActionDefinitionNode> actions = PsiTreeUtil.findChildrenOfType(element, ActionDefinitionNode.class);
for (PsiElement action : actions) {
treeElements.add(new BallerinaStructureViewElement(action));
}
// Convert the list to an array and return.
return treeElements.toArray(new TreeElement[treeElements.size()]);
} else if (element instanceof ServiceDefinitionNode) {
// If the element is a ServiceDefinitionNode instance, we get all resources.
List<TreeElement> treeElements = new ArrayList<>();
// Add resources.
Collection<ResourceDefinitionNode> resources = PsiTreeUtil.findChildrenOfType(element, ResourceDefinitionNode.class);
for (PsiElement resource : resources) {
treeElements.add(new BallerinaStructureViewElement(resource));
}
// Convert the list to an array and return.
return treeElements.toArray(new TreeElement[treeElements.size()]);
} else if (element instanceof FunctionDefinitionNode || element instanceof ResourceDefinitionNode || element instanceof ActionDefinitionNode) {
// If the element is a FunctionDefinitionNode instance, we get all workers.
List<TreeElement> treeElements = new ArrayList<>();
// Add workers.
Collection<WorkerDeclarationNode> workers = PsiTreeUtil.findChildrenOfType(element, WorkerDeclarationNode.class);
for (PsiElement worker : workers) {
treeElements.add(new BallerinaStructureViewElement(worker));
}
// Convert the list to an array and return.
return treeElements.toArray(new TreeElement[treeElements.size()]);
}
// If the element type other than what we check above, return an empty array.
return new TreeElement[0];
}
Aggregations