Skip to content

Commit

Permalink
Resolve conflict and apply project API changes
Browse files Browse the repository at this point in the history
  • Loading branch information
lnash94 committed Aug 22, 2023
1 parent bada06f commit e886632
Show file tree
Hide file tree
Showing 18 changed files with 197 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,9 @@ public enum DiagnosticMessages {
DiagnosticSeverity.WARNING),
OAS_CONVERTOR_114("OAS_CONVERTOR_114", "Generated OpenAPI definition does not contain information " +
"for Ballerina type '%s'. ", DiagnosticSeverity.WARNING),
OAS_CONVERTOR_115("OAS_CONVERTOR_115", "Failed to parser the Number value due to: %s ",
DiagnosticSeverity.ERROR),
"for Ballerina type '%s'. ", DiagnosticSeverity.WARNING),
//todo resolve conflicts
OAS_CONVERTOR_115("OAS_CONVERTOR_115", "Given Ballerina file does not contain any HTTP service.",
DiagnosticSeverity.ERROR),
OAS_CONVERTOR_116("OAS_CONVERTOR_116", "Failed to parser the Number value due to: %s ",
DiagnosticSeverity.ERROR);

private final String code;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2022, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 Inc. licenses this file to you under the Apache License,
* WSO2 LLC. licenses this file to you 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
Expand All @@ -20,8 +20,9 @@
import java.util.Optional;

/**
* This @link ConstraintAnnotation} class represents the constraint annotations.
*
* @since 1.2.0
* @since 1.9.0
*/
public class ConstraintAnnotation {
private final String minValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
import io.ballerina.compiler.syntax.tree.NodeVisitor;
import io.ballerina.compiler.syntax.tree.TypeDefinitionNode;

import java.util.LinkedList;
import java.util.List;
import java.util.LinkedHashSet;

/**
* Visitor to get the TypeDefinitionNode and ListenerDeclarationNodes.
Expand All @@ -32,8 +31,8 @@
*/
public class ModuleMemberVisitor extends NodeVisitor {

LinkedList<TypeDefinitionNode> typeDefinitionNodes = new LinkedList<>();
LinkedList<ListenerDeclarationNode> listenerDeclarationNodes = new LinkedList<>();
LinkedHashSet<TypeDefinitionNode> typeDefinitionNodes = new LinkedHashSet<>();
LinkedHashSet<ListenerDeclarationNode> listenerDeclarationNodes = new LinkedHashSet<>();

@Override
public void visit(TypeDefinitionNode typeDefinitionNode) {
Expand All @@ -45,11 +44,11 @@ public void visit(ListenerDeclarationNode listenerDeclarationNode) {
listenerDeclarationNodes.add(listenerDeclarationNode);
}

public List<TypeDefinitionNode> getTypeDefinitionNodes() {
public LinkedHashSet<TypeDefinitionNode> getTypeDefinitionNodes() {
return typeDefinitionNodes;
}

public List<ListenerDeclarationNode> getListenerDeclarationNodes() {
public LinkedHashSet<ListenerDeclarationNode> getListenerDeclarationNodes() {
return listenerDeclarationNodes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@
import io.ballerina.compiler.api.symbols.UnionTypeSymbol;
import io.ballerina.compiler.syntax.tree.AnnotationNode;
import io.ballerina.compiler.syntax.tree.ExpressionNode;
import io.ballerina.compiler.syntax.tree.IntersectionTypeDescriptorNode;
import io.ballerina.compiler.syntax.tree.MappingConstructorExpressionNode;
import io.ballerina.compiler.syntax.tree.MappingFieldNode;
import io.ballerina.compiler.syntax.tree.MetadataNode;
import io.ballerina.compiler.syntax.tree.ModulePartNode;
import io.ballerina.compiler.syntax.tree.Node;
import io.ballerina.compiler.syntax.tree.NodeList;
import io.ballerina.compiler.syntax.tree.NonTerminalNode;
import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode;
import io.ballerina.compiler.syntax.tree.RecordFieldNode;
import io.ballerina.compiler.syntax.tree.RecordTypeDescriptorNode;
import io.ballerina.compiler.syntax.tree.SpecificFieldNode;
import io.ballerina.compiler.syntax.tree.SyntaxKind;
import io.ballerina.compiler.syntax.tree.TypeDefinitionNode;
Expand All @@ -70,6 +71,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
Expand All @@ -89,14 +91,13 @@
public class OpenAPIComponentMapper {
private final Components components;
private final List<OpenAPIConverterDiagnostic> diagnostics;
private final NonTerminalNode rootNode;
private final HashSet<String> visitedTypeDefinitionNames = new HashSet<>();
private final LinkedHashSet<TypeDefinitionNode> typeDefinitionNodes;


public OpenAPIComponentMapper(Components components, NonTerminalNode rootNode) {
public OpenAPIComponentMapper(Components components, ModuleMemberVisitor moduleMemberVisitor) {
this.components = components;
this.rootNode = rootNode;
this.diagnostics = new ArrayList<>();
this.typeDefinitionNodes = moduleMemberVisitor.getTypeDefinitionNodes();
}

public List<OpenAPIConverterDiagnostic> getDiagnostics() {
Expand All @@ -122,24 +123,22 @@ public void createComponentSchema(Map<String, Schema> schema, TypeSymbol typeSym
}
TypeReferenceTypeSymbol typeRef = (TypeReferenceTypeSymbol) typeSymbol;
TypeSymbol type = typeRef.typeDescriptor();
// Handle record type request body
if (type.typeKind() == TypeDescKind.INTERSECTION) {
type = excludeReadonlyIfPresent(type);
}

//Access module part node for finding the node to given typeSymbol.
//TODO: this works for module reference.
ModulePartNode modulePartNode = rootNode.syntaxTree().rootNode();
NonTerminalNode nonTerminalNode = modulePartNode.findNode(typeSymbol.getLocation().get().textRange());
ConstraintAnnotation.ConstraintAnnotationBuilder constraintBuilder =
new ConstraintAnnotation.ConstraintAnnotationBuilder();
if (nonTerminalNode instanceof TypeDefinitionNode) {
TypeDefinitionNode node = (TypeDefinitionNode) nonTerminalNode;

if (node.metadata().isPresent()) {
extractedConstraintAnnotation(node.metadata().get(), constraintBuilder);
((TypeReferenceTypeSymbol) typeSymbol).definition().getName().ifPresent(name -> {
for (TypeDefinitionNode typeDefinitionNode : typeDefinitionNodes) {
if (typeDefinitionNode.typeName().text().equals(name)) {
if (typeDefinitionNode.metadata().isPresent()) {
extractedConstraintAnnotation(typeDefinitionNode.metadata().get(), constraintBuilder);
}
}
}
}
});
ConstraintAnnotation constraintAnnot = constraintBuilder.build();

switch (type.typeKind()) {
Expand Down Expand Up @@ -366,23 +365,43 @@ private ObjectSchema generateObjectSchemaFromRecordFields(Map<String, Schema> sc
List<String> required = new ArrayList<>();
componentSchema.setDescription(apiDocs.get(componentName));
Map<String, Schema> schemaProperties = new LinkedHashMap<>();
RecordTypeDescriptorNode record = null;
// Get the record type descriptor node from given record type symbol
for (TypeDefinitionNode typeDefinitionNode : typeDefinitionNodes) {
if (typeDefinitionNode.typeName().text().equals(componentName)) {
if (typeDefinitionNode.typeDescriptor().kind().equals(SyntaxKind.RECORD_TYPE_DESC)) {
record = (RecordTypeDescriptorNode) typeDefinitionNode.typeDescriptor();
} else if (typeDefinitionNode.typeDescriptor().kind().equals(SyntaxKind.INTERSECTION_TYPE_DESC)) {
IntersectionTypeDescriptorNode intersecNode =
(IntersectionTypeDescriptorNode) typeDefinitionNode.typeDescriptor();
Node leftTypeDesc = intersecNode.leftTypeDesc();
Node rightTypeDesc = intersecNode.rightTypeDesc();
if (leftTypeDesc.kind().equals(SyntaxKind.RECORD_TYPE_DESC)) {
record = (RecordTypeDescriptorNode) leftTypeDesc;
}
if (rightTypeDesc.kind().equals(SyntaxKind.RECORD_TYPE_DESC)) {
record = (RecordTypeDescriptorNode) rightTypeDesc;
}
}
}
}

for (Map.Entry<String, RecordFieldSymbol> field : rfields.entrySet()) {
ConstraintAnnotation.ConstraintAnnotationBuilder constraintBuilder =
new ConstraintAnnotation.ConstraintAnnotationBuilder();

if (!(rootNode instanceof QualifiedNameReferenceNode)) {
ModulePartNode modulePartNode = rootNode.syntaxTree().rootNode();
NonTerminalNode node = modulePartNode.findNode(field.getValue().getLocation().get().textRange());
if (node instanceof RecordFieldNode) {
RecordFieldNode fieldNode = (RecordFieldNode) modulePartNode.
findNode(field.getValue().getLocation().get().textRange());
Optional<MetadataNode> metadata = fieldNode.metadata();
metadata.ifPresent(metadataNode -> extractedConstraintAnnotation(metadataNode, constraintBuilder));
if (record != null) {
for (Node node : record.fields()) {
if (node instanceof RecordFieldNode) {
RecordFieldNode fieldNode = (RecordFieldNode) node;
if (fieldNode.fieldName().toString().equals(field.getKey())) {
Optional<MetadataNode> metadata = fieldNode.metadata();
metadata.ifPresent(metadataNode -> extractedConstraintAnnotation(metadataNode,
constraintBuilder));
}
}
}
}

ConstraintAnnotation constraintAnnot = constraintBuilder.build();

String fieldName = ConverterCommonUtils.unescapeIdentifier(field.getKey().trim());
if (!field.getValue().isOptional()) {
required.add(fieldName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@ public class OpenAPIHeaderMapper {
private final Components components;
private final SemanticModel semanticModel;
private final Map<String, String> apidocs;
private final ModuleMemberVisitor moduleMemberVisitor;

public OpenAPIHeaderMapper(Components components, SemanticModel semanticModel, Map<String, String> apidocs) {
public OpenAPIHeaderMapper(Components components, SemanticModel semanticModel, Map<String, String> apidocs,
ModuleMemberVisitor moduleMemberVisitor) {
this.apidocs = apidocs;
this.components = components;
this.semanticModel = semanticModel;
this.moduleMemberVisitor = moduleMemberVisitor;
}

/**
Expand All @@ -86,7 +89,7 @@ public List<Parameter> setHeaderParameter(RequiredParameterNode headerParam) {

if (headerDetailNode.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) {
SimpleNameReferenceNode refNode = (SimpleNameReferenceNode) headerDetailNode;
headerTypeSchema = handleReference(semanticModel, components, refNode);
headerTypeSchema = handleReference(semanticModel, components, refNode, moduleMemberVisitor);
} else {
headerTypeSchema = ConverterCommonUtils.getOpenApiSchema(getHeaderType(headerParam));
}
Expand Down Expand Up @@ -126,7 +129,7 @@ public List<Parameter> setHeaderParameter(DefaultableParameterNode headerParam)
Schema<?> headerTypeSchema;
if (headerParam.typeName().kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) {
SimpleNameReferenceNode refNode = (SimpleNameReferenceNode) headerParam.typeName();
headerTypeSchema = handleReference(semanticModel, components, refNode);
headerTypeSchema = handleReference(semanticModel, components, refNode, moduleMemberVisitor);
} else {
headerTypeSchema = ConverterCommonUtils.getOpenApiSchema(getHeaderType(headerParam));
}
Expand Down Expand Up @@ -184,7 +187,7 @@ private void completeHeaderParameter(List<Parameter> parameters, String headerNa
Schema<?> itemSchema;
if (kind == SyntaxKind.SIMPLE_NAME_REFERENCE) {
SimpleNameReferenceNode refNode = (SimpleNameReferenceNode) arrayNode.memberTypeDesc();
itemSchema = handleReference(semanticModel, components, refNode);
itemSchema = handleReference(semanticModel, components, refNode, moduleMemberVisitor);
} else {
itemSchema = ConverterCommonUtils.getOpenApiSchema(kind);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import static io.ballerina.openapi.converter.Constants.WILD_CARD_CONTENT_KEY;
import static io.ballerina.openapi.converter.Constants.WILD_CARD_SUMMARY;
import static io.ballerina.openapi.converter.utils.ConverterCommonUtils.extractCustomMediaType;
import static io.ballerina.openapi.converter.utils.ConverterCommonUtils.unescapeIdentifier;

/**
* OpenAPIParameterMapper provides functionality for converting ballerina parameter to OAS parameter model.
Expand All @@ -69,20 +70,23 @@ public class OpenAPIParameterMapper {
private final List<OpenAPIConverterDiagnostic> errors = new ArrayList<>();
private final Components components;
private final SemanticModel semanticModel;
private final ModuleMemberVisitor moduleMemberVisitor;

public List<OpenAPIConverterDiagnostic> getErrors() {
return errors;
}

public OpenAPIParameterMapper(FunctionDefinitionNode functionDefinitionNode,
OperationAdaptor operationAdaptor, Map<String, String> apidocs,
Components components, SemanticModel semanticModel) {
Components components, SemanticModel semanticModel,
ModuleMemberVisitor moduleMemberVisitor) {

this.functionDefinitionNode = functionDefinitionNode;
this.operationAdaptor = operationAdaptor;
this.apidocs = apidocs;
this.components = components;
this.semanticModel = semanticModel;
this.moduleMemberVisitor = moduleMemberVisitor;
}


Expand All @@ -100,7 +104,7 @@ public void getResourceInputs(Components components, SemanticModel semanticModel
SeparatedNodeList<ParameterNode> parameterList = functionSignature.parameters();
for (ParameterNode parameterNode : parameterList) {
OpenAPIQueryParameterMapper queryParameterMapper = new OpenAPIQueryParameterMapper(apidocs, components,
semanticModel);
semanticModel, moduleMemberVisitor);
if (parameterNode.kind() == SyntaxKind.REQUIRED_PARAM) {
RequiredParameterNode requiredParameterNode = (RequiredParameterNode) parameterNode;
// Handle query parameter
Expand Down Expand Up @@ -159,11 +163,12 @@ private void createPathParameters(List<Parameter> parameters, NodeList<Node> pat
ResourcePathParameterNode pathParam = (ResourcePathParameterNode) param;
if (pathParam.typeDescriptor().kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) {
SimpleNameReferenceNode queryNode = (SimpleNameReferenceNode) pathParam.typeDescriptor();
OpenAPIComponentMapper componentMapper = new OpenAPIComponentMapper(components, pathParam);
OpenAPIComponentMapper componentMapper = new OpenAPIComponentMapper(components,
moduleMemberVisitor);
TypeSymbol typeSymbol = (TypeSymbol) semanticModel.symbol(queryNode).orElseThrow();
componentMapper.createComponentSchema(components.getSchemas(), typeSymbol);
Schema schema = new Schema();
schema.set$ref(ConverterCommonUtils.unescapeIdentifier(queryNode.name().text().trim()));
schema.set$ref(unescapeIdentifier(queryNode.name().text().trim()));
pathParameterOAS.setSchema(schema);
} else {
pathParameterOAS.schema(ConverterCommonUtils.getOpenApiSchema(
Expand Down Expand Up @@ -195,12 +200,13 @@ private void handleAnnotationParameters(Components components,
for (AnnotationNode annotation: annotations) {
if ((annotation.annotReference().toString()).trim().equals(Constants.HTTP_HEADER)) {
// Handle headers.
OpenAPIHeaderMapper openAPIHeaderMapper = new OpenAPIHeaderMapper(components, semanticModel, apidocs);
OpenAPIHeaderMapper openAPIHeaderMapper = new OpenAPIHeaderMapper(components, semanticModel, apidocs,
moduleMemberVisitor);
parameters.addAll(openAPIHeaderMapper.setHeaderParameter(requiredParameterNode));
} else if ((annotation.annotReference().toString()).trim().equals(Constants.HTTP_QUERY)) {
// Handle query parameter.
OpenAPIQueryParameterMapper openAPIQueryParameterMapper = new OpenAPIQueryParameterMapper(apidocs,
components, semanticModel);
components, semanticModel, moduleMemberVisitor);
parameters.add(openAPIQueryParameterMapper.createQueryParameter(requiredParameterNode));
} else if ((annotation.annotReference().toString()).trim().equals(Constants.HTTP_PAYLOAD) &&
(!Constants.GET.toLowerCase(Locale.ENGLISH).equalsIgnoreCase(
Expand All @@ -210,8 +216,9 @@ private void handleAnnotationParameters(Components components,
Optional<String> customMediaType = extractCustomMediaType(functionDefinitionNode);
OpenAPIRequestBodyMapper openAPIRequestBodyMapper = customMediaType.map(
value -> new OpenAPIRequestBodyMapper(components,
operationAdaptor, semanticModel, value)).orElse(new OpenAPIRequestBodyMapper(components,
operationAdaptor, semanticModel));
operationAdaptor, semanticModel, value, moduleMemberVisitor)).orElse(
new OpenAPIRequestBodyMapper(components,
operationAdaptor, semanticModel, moduleMemberVisitor));
openAPIRequestBodyMapper.handlePayloadAnnotation(requiredParameterNode, schema, annotation, apidocs);
errors.addAll(openAPIRequestBodyMapper.getDiagnostics());
} else if ((annotation.annotReference().toString()).trim().equals(Constants.HTTP_PAYLOAD) &&
Expand All @@ -233,12 +240,13 @@ private List<Parameter> handleDefaultableAnnotationParameters(DefaultableParamet
for (AnnotationNode annotation: annotations) {
if ((annotation.annotReference().toString()).trim().equals(Constants.HTTP_HEADER)) {
// Handle headers.
OpenAPIHeaderMapper openAPIHeaderMapper = new OpenAPIHeaderMapper(components, semanticModel, apidocs);
OpenAPIHeaderMapper openAPIHeaderMapper = new OpenAPIHeaderMapper(components, semanticModel, apidocs,
moduleMemberVisitor);
parameters = openAPIHeaderMapper.setHeaderParameter(defaultableParameterNode);
} else if ((annotation.annotReference().toString()).trim().equals(Constants.HTTP_QUERY)) {
// Handle query parameter.
OpenAPIQueryParameterMapper openAPIQueryParameterMapper = new OpenAPIQueryParameterMapper(apidocs,
components, semanticModel);
components, semanticModel, moduleMemberVisitor);
parameters.add(openAPIQueryParameterMapper.createQueryParameter(defaultableParameterNode));
}
}
Expand Down
Loading

0 comments on commit e886632

Please sign in to comment.