Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…llerina-dev-tools into open-api-support
  • Loading branch information
KavinduZoysa committed Oct 7, 2024
2 parents 556f5b6 + 207c421 commit 187bcf9
Show file tree
Hide file tree
Showing 197 changed files with 9,304 additions and 8,390 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@
import io.ballerina.compiler.syntax.tree.Node;
import io.ballerina.compiler.syntax.tree.NonTerminalNode;
import io.ballerina.compiler.syntax.tree.SyntaxKind;
import io.ballerina.flowmodelgenerator.core.central.ConnectorResponse;
import io.ballerina.flowmodelgenerator.core.central.LocalIndexCentral;
import io.ballerina.flowmodelgenerator.core.central.RemoteCentral;
import io.ballerina.flowmodelgenerator.core.model.AvailableNode;
import io.ballerina.flowmodelgenerator.core.model.Category;
import io.ballerina.flowmodelgenerator.core.model.Codedata;
import io.ballerina.flowmodelgenerator.core.model.Item;
import io.ballerina.flowmodelgenerator.core.model.Metadata;
import io.ballerina.flowmodelgenerator.core.model.NodeBuilder;
import io.ballerina.flowmodelgenerator.core.model.NodeKind;
import io.ballerina.flowmodelgenerator.core.model.node.NewConnection;
import io.ballerina.projects.Document;
import io.ballerina.tools.text.LinePosition;
import io.ballerina.tools.text.TextRange;
Expand All @@ -61,12 +65,14 @@ public class AvailableNodesGenerator {
private final SemanticModel semanticModel;
private final Document document;
private final Gson gson;
private final boolean forceAssign;

public AvailableNodesGenerator(SemanticModel semanticModel, Document document) {
public AvailableNodesGenerator(SemanticModel semanticModel, Document document, boolean forceAssign) {
this.rootBuilder = new Category.Builder(null).name(Category.Name.ROOT);
this.gson = new Gson();
this.semanticModel = semanticModel;
this.document = document;
this.forceAssign = forceAssign;
}

public JsonArray getAvailableNodes(LinePosition position) {
Expand Down Expand Up @@ -133,34 +139,45 @@ private void setDefaultNodes() {
true
);

this.rootBuilder
.stepIn(Category.Name.STATEMENT)
.node(NodeKind.ASSIGN)
this.rootBuilder.stepIn(Category.Name.STATEMENT).node(NodeKind.ASSIGN);

if (!forceAssign) {
this.rootBuilder.stepIn(Category.Name.STATEMENT)
.node(function)
.stepOut()
.stepIn(Category.Name.CONTROL)
.node(NodeKind.IF)
.node(NodeKind.MATCH)
.node(NodeKind.WHILE)
.node(NodeKind.FOREACH)
.node(NodeKind.RETURN)
.stepOut()
.stepIn(Category.Name.DATA)
.node(NodeKind.DATA_MAPPER)
.node(NodeKind.RETRY);
}

this.rootBuilder.stepIn(Category.Name.CONTROL)
.node(NodeKind.IF)
.node(NodeKind.MATCH)
.node(NodeKind.WHILE)
.node(NodeKind.FOREACH)
.node(NodeKind.RETURN);

if (!forceAssign) {
this.rootBuilder.stepIn(Category.Name.DATA)
.node(NodeKind.JSON_PAYLOAD)
.node(NodeKind.XML_PAYLOAD)
.node(NodeKind.BINARY_DATA)
.node(NodeKind.DATA_MAPPER)
.stepOut()
.node(NodeKind.BINARY_DATA);
}

this.rootBuilder
.stepIn(Category.Name.ERROR_HANDLING)
.node(NodeKind.ERROR_HANDLER)
// TODO: Uncomment when error handling is implemented
// .node(NodeKind.ERROR_HANDLER)
.node(NodeKind.FAIL)
.node(NodeKind.PANIC)
.stepOut()
.stepIn(Category.Name.CONCURRENCY)
.node(NodeKind.TRANSACTION)
.node(NodeKind.LOCK)
.node(NodeKind.START)
.stepOut();
// TODO: Uncomment when concurrency is implemented
// this.rootBuilder
// .stepIn(Category.Name.CONCURRENCY)
// .node(NodeKind.TRANSACTION)
// .node(NodeKind.COMMIT)
// .node(NodeKind.ROLLBACK)
// .node(NodeKind.LOCK)
// .node(NodeKind.START)
// .stepOut();
}

private void setStopNode(NonTerminalNode node) {
Expand Down Expand Up @@ -203,11 +220,16 @@ private Optional<Category> getConnection(Symbol symbol) {
.node(NodeKind.NEW_CONNECTION)
.org(moduleSymbol.id().orgName())
.module(moduleSymbol.getName().orElseThrow())
.version(moduleSymbol.id().version())
.object("Client")
.symbol("init")
.build();
List<Item> connections = LocalIndexCentral.getInstance().getConnectorActions(codedata);

if (connections == null) {
connections = fetchConnections(codedata);
}

Metadata metadata = new Metadata.Builder<>(null)
.label(symbol.getName().orElseThrow())
.build();
Expand All @@ -216,4 +238,32 @@ private Optional<Category> getConnection(Symbol symbol) {
return Optional.empty();
}
}

private static List<Item> fetchConnections(Codedata codedata) {
List<Item> connectorActions = new ArrayList<>();
ConnectorResponse connector = RemoteCentral.getInstance()
.connector(codedata.org(), codedata.module(), codedata.version(), codedata.object());
for (ConnectorResponse.Function function : connector.functions()) {
if (function.name().equals(NewConnection.INIT_SYMBOL)) {
continue;
}
NodeBuilder actionBuilder = NodeBuilder.getNodeFromKind(NodeKind.ACTION_CALL);
actionBuilder
.metadata()
.label(function.name())
.icon(connector.icon())
.description(function.documentation())
.stepOut()
.codedata()
.node(NodeKind.ACTION_CALL)
.org(codedata.org())
.module(codedata.module())
.object(codedata.object())
.id(String.valueOf(connector.id()))
.symbol(function.name());
connectorActions.add(actionBuilder.buildAvailableNode());
}
return connectorActions;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.ballerina.compiler.syntax.tree.CheckExpressionNode;
import io.ballerina.compiler.syntax.tree.ClientResourceAccessActionNode;
import io.ballerina.compiler.syntax.tree.CommentNode;
import io.ballerina.compiler.syntax.tree.CommitActionNode;
import io.ballerina.compiler.syntax.tree.CompoundAssignmentStatementNode;
import io.ballerina.compiler.syntax.tree.ContinueStatementNode;
import io.ballerina.compiler.syntax.tree.DoStatementNode;
Expand Down Expand Up @@ -80,6 +81,7 @@
import io.ballerina.compiler.syntax.tree.SeparatedNodeList;
import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode;
import io.ballerina.compiler.syntax.tree.StartActionNode;
import io.ballerina.compiler.syntax.tree.StatementNode;
import io.ballerina.compiler.syntax.tree.SyntaxKind;
import io.ballerina.compiler.syntax.tree.TemplateExpressionNode;
import io.ballerina.compiler.syntax.tree.Token;
Expand All @@ -94,14 +96,17 @@
import io.ballerina.flowmodelgenerator.core.model.NodeBuilder;
import io.ballerina.flowmodelgenerator.core.model.NodeKind;
import io.ballerina.flowmodelgenerator.core.model.Property;
import io.ballerina.flowmodelgenerator.core.model.node.ActionCall;
import io.ballerina.flowmodelgenerator.core.model.node.Assign;
import io.ballerina.flowmodelgenerator.core.model.node.BinaryData;
import io.ballerina.flowmodelgenerator.core.model.node.DataMapper;
import io.ballerina.flowmodelgenerator.core.model.node.Fail;
import io.ballerina.flowmodelgenerator.core.model.node.FunctionCall;
import io.ballerina.flowmodelgenerator.core.model.node.If;
import io.ballerina.flowmodelgenerator.core.model.node.JsonPayload;
import io.ballerina.flowmodelgenerator.core.model.node.Panic;
import io.ballerina.flowmodelgenerator.core.model.node.Return;
import io.ballerina.flowmodelgenerator.core.model.node.Rollback;
import io.ballerina.flowmodelgenerator.core.model.node.Start;
import io.ballerina.flowmodelgenerator.core.model.node.XmlPayload;
import io.ballerina.tools.text.LinePosition;
Expand Down Expand Up @@ -132,16 +137,18 @@ class CodeAnalyzer extends NodeVisitor {
private final String connectionScope;
private final TextDocument textDocument;
private final String defaultModuleName;
private final boolean forceAssign;

public CodeAnalyzer(SemanticModel semanticModel, String connectionScope, Map<String, LineRange> dataMappings,
TextDocument textDocument, String defaultModuleName) {
TextDocument textDocument, String defaultModuleName, boolean forceAssign) {
this.flowNodeList = new ArrayList<>();
this.semanticModel = semanticModel;
this.flowNodeBuilderStack = new Stack<>();
this.dataMappings = dataMappings;
this.connectionScope = connectionScope;
this.textDocument = textDocument;
this.defaultModuleName = defaultModuleName;
this.forceAssign = forceAssign;
}

@Override
Expand Down Expand Up @@ -257,9 +264,10 @@ private void handleActionNode(ActionNode actionNode, String methodName, Expressi
.org(orgName)
.module(moduleName)
.object("Client")
.version(symbol.get().getModule().get().id().version())
.symbol(methodName)
.build();
FlowNode nodeTemplate = LocalIndexCentral.getInstance().getNodeTemplate(codedata);
FlowNode nodeTemplate = ActionCall.getNodeTemplate(codedata);
if (nodeTemplate == null) {
handleExpressionNode(actionNode);
return;
Expand Down Expand Up @@ -389,6 +397,9 @@ private void checkForNewConnection(NewExpressionNode newExpressionNode,

@Override
public void visit(TemplateExpressionNode templateExpressionNode) {
if (forceAssign) {
return;
}
if (templateExpressionNode.kind() == SyntaxKind.XML_TEMPLATE_EXPRESSION) {
startNode(NodeKind.XML_PAYLOAD)
.metadata()
Expand All @@ -400,6 +411,9 @@ public void visit(TemplateExpressionNode templateExpressionNode) {

@Override
public void visit(ByteArrayLiteralNode byteArrayLiteralNode) {
if (forceAssign) {
return;
}
startNode(NodeKind.BINARY_DATA)
.metadata()
.stepOut()
Expand All @@ -414,6 +428,7 @@ public void visit(VariableDeclarationNode variableDeclarationNode) {
}
ExpressionNode initializerNode = initializer.get();
this.typedBindingPatternNode = variableDeclarationNode.typedBindingPattern();

initializerNode.accept(this);

// Generate the default expression node if a node is not built
Expand Down Expand Up @@ -520,6 +535,10 @@ public void visit(FunctionCallExpressionNode functionCallExpressionNode) {
return;
}

if (forceAssign && this.typedBindingPatternNode != null) {
return;
}

FunctionSymbol functionSymbol = (FunctionSymbol) symbol.get();
String orgName = CommonUtils.getOrgName(functionSymbol);
NameReferenceNode nameReferenceNode = functionCallExpressionNode.functionName();
Expand All @@ -532,8 +551,9 @@ public void visit(FunctionCallExpressionNode functionCallExpressionNode) {
.org(orgName)
.module(moduleName)
.symbol(functionName)
.version(functionSymbol.getModule().get().id().version())
.build();
FlowNode nodeTemplate = LocalIndexCentral.getInstance().getNodeTemplate(codedata);
FlowNode nodeTemplate = FunctionCall.getNodeTemplate(codedata);
if (nodeTemplate == null) {
handleExpressionNode(functionCallExpressionNode);
return;
Expand All @@ -549,6 +569,7 @@ public void visit(FunctionCallExpressionNode functionCallExpressionNode) {
.org(nodeTemplate.codedata().org())
.module(nodeTemplate.codedata().module())
.object(nodeTemplate.codedata().object())
.version(nodeTemplate.codedata().version())
.symbol(nodeTemplate.codedata().symbol());

functionSymbol.typeDescriptor().params().ifPresent(params -> nodeBuilder.properties().functionArguments(
Expand All @@ -572,6 +593,7 @@ public void visit(FunctionCallExpressionNode functionCallExpressionNode) {
.codedata()
.org(orgName)
.module(defaultModuleName)
.version(functionSymbol.getModule().get().id().version())
.symbol(functionName);
functionSymbol.typeDescriptor().params().ifPresent(
params -> nodeBuilder.properties()
Expand Down Expand Up @@ -675,12 +697,51 @@ public void visit(ForEachStatementNode forEachStatementNode) {

@Override
public void visit(RollbackStatementNode rollbackStatementNode) {
handleDefaultStatementNode(rollbackStatementNode, () -> super.visit(rollbackStatementNode));
startNode(NodeKind.ROLLBACK);
Optional<ExpressionNode> optExpr = rollbackStatementNode.expression();
if (optExpr.isPresent()) {
ExpressionNode expr = optExpr.get();
expr.accept(this);
nodeBuilder.properties().expression(expr, Rollback.ROLLBACK_EXPRESSION_DOC);
}
endNode(rollbackStatementNode);
}

@Override
public void visit(RetryStatementNode retryStatementNode) {
handleDefaultStatementNode(retryStatementNode, () -> super.visit(retryStatementNode));
int retryCount = retryStatementNode.arguments().isEmpty() ? 3 :
Integer.parseInt(retryStatementNode.arguments()
.map(arg -> arg.arguments().get(0)).get().toString());

StatementNode statementNode = retryStatementNode.retryBody();
if (statementNode.kind() == SyntaxKind.BLOCK_STATEMENT) {
startNode(NodeKind.RETRY)
.properties().retryCount(retryCount);

Branch.Builder branchBuilder =
startBranch(Branch.BODY_LABEL, NodeKind.BODY, Branch.BranchKind.BLOCK, Branch.Repeatable.ONE);
analyzeBlock((BlockStatementNode) statementNode, branchBuilder);
endBranch(branchBuilder, statementNode);
retryStatementNode.onFailClause().ifPresent(this::processOnFailClause);
endNode(retryStatementNode);
} else { // retry transaction node
TransactionStatementNode transactionStatementNode = (TransactionStatementNode) statementNode;
BlockStatementNode blockStatementNode = transactionStatementNode.blockStatement();
startNode(NodeKind.TRANSACTION)
.properties().retryCount(retryCount);
Branch.Builder branchBuilder =
startBranch(Branch.BODY_LABEL, NodeKind.BODY, Branch.BranchKind.BLOCK, Branch.Repeatable.ONE);
analyzeBlock(blockStatementNode, branchBuilder);
endBranch(branchBuilder, blockStatementNode);
transactionStatementNode.onFailClause().ifPresent(this::processOnFailClause);
endNode(retryStatementNode);
}
}

@Override
public void visit(CommitActionNode commitActionNode) {
startNode(NodeKind.COMMIT);
endNode();
}

@Override
Expand Down Expand Up @@ -770,7 +831,8 @@ private void handleConstructorExpressionNode(ExpressionNode constructorExprNode)

Optional<Symbol> parentSymbol = semanticModel.symbol(parent);
if (parentSymbol.isPresent() && CommonUtils.getRawType(
((VariableSymbol) parentSymbol.get()).typeDescriptor()).typeKind() == TypeDescKind.JSON) {
((VariableSymbol) parentSymbol.get()).typeDescriptor()).typeKind() == TypeDescKind.JSON &&
!forceAssign) {
startNode(NodeKind.JSON_PAYLOAD)
.metadata()
.description(JsonPayload.DESCRIPTION)
Expand All @@ -792,6 +854,7 @@ private void handleConstructorExpressionNode(ExpressionNode constructorExprNode)
}

// Utility methods

/**
* It's the responsibility of the parent node to add the children nodes when building the diagram. Hence, the method
* only adds the node to the diagram if there is no active parent node which is building its branches.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import io.ballerina.compiler.syntax.tree.SyntaxKind;
import io.ballerina.compiler.syntax.tree.SyntaxTree;
import io.ballerina.compiler.syntax.tree.TypedBindingPatternNode;
import io.ballerina.flowmodelgenerator.core.central.ConnectorResponse;
import io.ballerina.projects.Document;
import io.ballerina.tools.text.LinePosition;
import io.ballerina.tools.text.LineRange;
Expand Down Expand Up @@ -298,4 +299,11 @@ public static TypeSymbol getRawType(TypeSymbol typeDescriptor) {
}
return typeDescriptor;
}

public static Object getTypeConstraint(ConnectorResponse.Parameter param, String typeName) {
return switch (typeName) {
case "inclusion" -> param.inclusionType();
default -> typeName;
};
}
}
Loading

0 comments on commit 187bcf9

Please sign in to comment.