From cb735d156e970874959985678e8fa36aa4450e8e Mon Sep 17 00:00:00 2001 From: chamil321 Date: Mon, 19 Apr 2021 18:25:37 +0530 Subject: [PATCH] Add enums for error codes --- http-compiler-plugin-tests/build.gradle | 1 + .../http/compiler/CompilerPluginTest.java | 11 +- .../stdlib/http/compiler/Constants.java | 16 --- .../http/compiler/HttpDiagnosticCodes.java | 73 ++++++++++++ .../http/compiler/HttpResourceValidator.java | 106 +++++++----------- .../http/compiler/HttpServiceValidator.java | 7 +- 6 files changed, 123 insertions(+), 91 deletions(-) create mode 100644 http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpDiagnosticCodes.java diff --git a/http-compiler-plugin-tests/build.gradle b/http-compiler-plugin-tests/build.gradle index 213b150975..5b01e8242f 100644 --- a/http-compiler-plugin-tests/build.gradle +++ b/http-compiler-plugin-tests/build.gradle @@ -106,6 +106,7 @@ task copyPackageBala { } test { + systemProperty "ballerina.offline.flag", "true" useTestNG() } diff --git a/http-compiler-plugin-tests/src/test/java/io/ballerina/stdlib/http/compiler/CompilerPluginTest.java b/http-compiler-plugin-tests/src/test/java/io/ballerina/stdlib/http/compiler/CompilerPluginTest.java index 631cc5e93f..e90d04b86c 100644 --- a/http-compiler-plugin-tests/src/test/java/io/ballerina/stdlib/http/compiler/CompilerPluginTest.java +++ b/http-compiler-plugin-tests/src/test/java/io/ballerina/stdlib/http/compiler/CompilerPluginTest.java @@ -29,7 +29,6 @@ import org.testng.Assert; import org.testng.annotations.Test; -import java.io.PrintStream; import java.nio.file.Path; import java.nio.file.Paths; @@ -40,7 +39,6 @@ public class CompilerPluginTest { private static final Path RESOURCE_DIRECTORY = Paths.get("src", "test", "resources", "ballerina_sources") .toAbsolutePath(); - private static final PrintStream OUT = System.out; private static final Path DISTRIBUTION_PATH = Paths.get("build", "target", "ballerina-distribution") .toAbsolutePath(); @@ -58,7 +56,7 @@ public class CompilerPluginTest { private static final String HTTP_112 = "HTTP_112"; private static final String HTTP_113 = "HTTP_113"; - private static final String REMOTE_METHODS_NOT_ALLOWED = "`remote` methods are not allowed in http:Service"; + private static final String REMOTE_METHODS_NOT_ALLOWED = "remote methods are not allowed in http:Service"; private Package loadPackage(String path) { Path projectDirPath = RESOURCE_DIRECTORY.resolve(path); @@ -89,9 +87,10 @@ public void testInvalidMethodTypes() { PackageCompilation compilation = currentPackage.getCompilation(); DiagnosticResult diagnosticResult = compilation.diagnosticResult(); Assert.assertEquals(diagnosticResult.diagnosticCount(), 3); - assertError(diagnosticResult, 0, REMOTE_METHODS_NOT_ALLOWED, HTTP_101); - assertError(diagnosticResult, 1, REMOTE_METHODS_NOT_ALLOWED, HTTP_101); - assertError(diagnosticResult, 2, REMOTE_METHODS_NOT_ALLOWED, HTTP_101); + diagnosticResult.diagnostics().forEach(result -> { + Assert.assertEquals(result.diagnosticInfo().messageFormat(), REMOTE_METHODS_NOT_ALLOWED); + Assert.assertEquals(result.diagnosticInfo().code(), HTTP_101); + }); } @Test diff --git a/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/Constants.java b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/Constants.java index a718057995..1e66245c1d 100644 --- a/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/Constants.java +++ b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/Constants.java @@ -22,21 +22,6 @@ * Constants related to compiler plugin implementation. */ public class Constants { - - public static final String HTTP_101 = "HTTP_101"; - public static final String HTTP_102 = "HTTP_102"; - public static final String HTTP_103 = "HTTP_103"; - public static final String HTTP_104 = "HTTP_104"; - public static final String HTTP_105 = "HTTP_105"; - public static final String HTTP_106 = "HTTP_106"; - public static final String HTTP_107 = "HTTP_107"; - public static final String HTTP_108 = "HTTP_108"; - public static final String HTTP_109 = "HTTP_109"; - public static final String HTTP_110 = "HTTP_110"; - public static final String HTTP_111 = "HTTP_111"; - public static final String HTTP_112 = "HTTP_112"; - public static final String HTTP_113 = "HTTP_113"; - public static final String BALLERINA = "ballerina"; public static final String HTTP = "http"; public static final String REMOTE_KEYWORD = "remote"; @@ -49,5 +34,4 @@ public class Constants { public static final String CALLER_ANNOTATION_TYPE = "HttpCallerInfo"; public static final String HEADER_ANNOTATION_TYPE = "HttpHeader"; public static final String ALLOWED_RETURN_UNION = "anydata|http:Response|http:StatusCodeRecord|error"; - public static final String REMOTE_METHODS_NOT_ALLOWED = "`remote` methods are not allowed in http:Service"; } diff --git a/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpDiagnosticCodes.java b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpDiagnosticCodes.java new file mode 100644 index 0000000000..f9f31de409 --- /dev/null +++ b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpDiagnosticCodes.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 + * + * 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 io.ballerina.stdlib.http.compiler; + +import io.ballerina.tools.diagnostics.DiagnosticSeverity; + +import static io.ballerina.stdlib.http.compiler.Constants.ALLOWED_RETURN_UNION; +import static io.ballerina.stdlib.http.compiler.Constants.RESOURCE_CONFIG_ANNOTATION; +import static io.ballerina.tools.diagnostics.DiagnosticSeverity.ERROR; + +/** + * {@code DiagnosticCodes} is used to hold diagnostic codes. + */ +public enum HttpDiagnosticCodes { + HTTP_101("HTTP_101", "remote methods are not allowed in http:Service", ERROR), + HTTP_102("HTTP_102", "invalid resource method return type: expected '" + ALLOWED_RETURN_UNION + + "', but found '%s'", ERROR), + HTTP_103("HTTP_103", "invalid resource method annotation type: expected 'http:" + RESOURCE_CONFIG_ANNOTATION + + "', but found '%s'", ERROR), + HTTP_104("HTTP_104", "invalid annotation type on param '%s': expected one of the following types: " + + "'http:Payload', 'http:CallerInfo', 'http:Headers'", ERROR), + HTTP_105("HTTP_105", "invalid resource parameter '%s'", ERROR), + HTTP_106("HTTP_106", "invalid resource parameter type: '%s'", ERROR), + HTTP_107("HTTP_107", "invalid payload parameter type: '%s'", ERROR), + HTTP_108("HTTP_108", "invalid multiple resource parameter annotations for '%s'" + + ": expected one of the following types: 'http:Payload', 'http:CallerInfo', 'http:Headers'", ERROR), + HTTP_109("HTTP_109", "invalid type of header param '%s': expected 'string' or 'string[]'", ERROR), + HTTP_110("HTTP_110", "invalid union type of header param '%s': a string or an array of a string can " + + "only be union with '()'. Eg: string|() or string[]|()", ERROR), + HTTP_111("HTTP_111", "invalid type of caller param '%s': expected 'http:Caller'", ERROR), + HTTP_112("HTTP_112", "invalid type of query param '%s': expected one of the 'string', 'int', 'float', " + + "'boolean', 'decimal' types or the array types of them", ERROR), + HTTP_113("HTTP_113", "invalid union type of query param '%s': 'string', 'int', 'float', 'boolean', " + + "'decimal' type or the array types of them can only be union with '()'. Eg: string? or int[]?", ERROR); + + private final String code; + private final String message; + private final DiagnosticSeverity severity; + + HttpDiagnosticCodes(String code, String message, DiagnosticSeverity severity) { + this.code = code; + this.message = message; + this.severity = severity; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } + + public DiagnosticSeverity getSeverity() { + return severity; + } +} diff --git a/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpResourceValidator.java b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpResourceValidator.java index f3ef48df09..2e07d84288 100644 --- a/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpResourceValidator.java +++ b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpResourceValidator.java @@ -47,30 +47,16 @@ import java.util.Optional; import java.util.stream.Collectors; -import static io.ballerina.stdlib.http.compiler.Constants.ALLOWED_RETURN_UNION; import static io.ballerina.stdlib.http.compiler.Constants.BALLERINA; import static io.ballerina.stdlib.http.compiler.Constants.CALLER_ANNOTATION_TYPE; import static io.ballerina.stdlib.http.compiler.Constants.CALLER_OBJ_NAME; import static io.ballerina.stdlib.http.compiler.Constants.HEADER_ANNOTATION_TYPE; import static io.ballerina.stdlib.http.compiler.Constants.HEADER_OBJ_NAME; import static io.ballerina.stdlib.http.compiler.Constants.HTTP; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_102; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_103; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_104; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_105; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_106; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_107; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_108; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_109; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_110; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_111; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_112; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_113; import static io.ballerina.stdlib.http.compiler.Constants.PAYLOAD_ANNOTATION_TYPE; import static io.ballerina.stdlib.http.compiler.Constants.REQUEST_OBJ_NAME; import static io.ballerina.stdlib.http.compiler.Constants.RESOURCE_CONFIG_ANNOTATION; import static io.ballerina.stdlib.http.compiler.Constants.RESPONSE_OBJ_NAME; -import static io.ballerina.tools.diagnostics.DiagnosticSeverity.ERROR; /** * Validates a ballerina http resource. @@ -109,9 +95,12 @@ private static void extractInputParamTypeAndValidate(SyntaxNodeAnalysisContext c if (resourceMethodSymbolOptional.isEmpty()) { return; } - List parameters = - ((ResourceMethodSymbol) resourceMethodSymbolOptional.get()).typeDescriptor().parameters(); - for (ParameterSymbol param : parameters) { + Optional> parametersOptional = + ((ResourceMethodSymbol) resourceMethodSymbolOptional.get()).typeDescriptor().params(); + if (parametersOptional.isEmpty()) { + return; + } + for (ParameterSymbol param : parametersOptional.get()) { String paramType = param.typeDescriptor().signature(); Optional nameOptional = param.getName(); String paramName = nameOptional.isEmpty() ? "" : nameOptional.get(); @@ -156,16 +145,13 @@ private static void extractInputParamTypeAndValidate(SyntaxNodeAnalysisContext c reportInvalidParameterType(ctx, member, paramType); } - } else if (kind == TypeDescKind.STRING || kind == TypeDescKind.INT || kind == TypeDescKind.FLOAT || - kind == TypeDescKind.DECIMAL || kind == TypeDescKind.BOOLEAN) { + } else if (isAllowedQueryParamType(kind)) { // Allowed query param types } else if (kind == TypeDescKind.ARRAY) { // Allowed query param array types TypeSymbol arrTypeSymbol = ((ArrayTypeSymbol) typeSymbol).memberTypeDescriptor(); TypeDescKind elementKind = arrTypeSymbol.typeKind(); - if (elementKind == TypeDescKind.STRING || elementKind == TypeDescKind.INT || - elementKind == TypeDescKind.FLOAT || elementKind == TypeDescKind.DECIMAL || - elementKind == TypeDescKind.BOOLEAN) { + if (isAllowedQueryParamType(elementKind)) { continue; } } else if (kind == TypeDescKind.UNION) { @@ -185,14 +171,14 @@ private static void extractInputParamTypeAndValidate(SyntaxNodeAnalysisContext c if (elementKind == TypeDescKind.ARRAY) { TypeSymbol arrTypeSymbol = ((ArrayTypeSymbol) type).memberTypeDescriptor(); TypeDescKind arrElementKind = arrTypeSymbol.typeKind(); - if (arrElementKind != TypeDescKind.STRING && arrElementKind != TypeDescKind.INT && - arrElementKind != TypeDescKind.FLOAT && arrElementKind != TypeDescKind.DECIMAL && - arrElementKind != TypeDescKind.BOOLEAN) { - reportInvalidQueryParameterType(ctx, member, paramName); + if (isAllowedQueryParamType(arrElementKind)) { + continue; + } + reportInvalidQueryParameterType(ctx, member, paramName); + } else { + if (elementKind == TypeDescKind.NIL || isAllowedQueryParamType(elementKind)) { + continue; } - } else if (elementKind != TypeDescKind.NIL && elementKind != TypeDescKind.STRING && - elementKind != TypeDescKind.INT && elementKind != TypeDescKind.FLOAT && - elementKind != TypeDescKind.DECIMAL && elementKind != TypeDescKind.BOOLEAN) { reportInvalidQueryParameterType(ctx, member, paramName); } } @@ -366,6 +352,11 @@ private static void extractInputParamTypeAndValidate(SyntaxNodeAnalysisContext c } } + private static boolean isAllowedQueryParamType(TypeDescKind kind) { + return kind == TypeDescKind.STRING || kind == TypeDescKind.INT || kind == TypeDescKind.FLOAT || + kind == TypeDescKind.DECIMAL || kind == TypeDescKind.BOOLEAN; + } + private static void extractReturnTypeAndValidate(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode member) { Optional returnTypeDescriptorNode = member.functionSignature().returnTypeDesc(); if (returnTypeDescriptorNode.isEmpty()) { @@ -478,87 +469,72 @@ private static boolean isHttpModuleType(String expectedType, TypeSymbol typeDesc private static void reportInvalidReturnType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String returnType) { - String msg = "invalid resource method return type: expected '" + ALLOWED_RETURN_UNION + - "', but found '" + returnType + "'"; - reportError(ctx, node, msg, HTTP_102); + updateDiagnostic(ctx, node, returnType, HttpDiagnosticCodes.HTTP_102); } private static void reportInvalidResourceAnnotation(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String annotName) { - String msg = "invalid resource method annotation type: expected 'http:" + RESOURCE_CONFIG_ANNOTATION + "', " + - "but found '" + annotName + "'"; - reportError(ctx, node, msg, HTTP_103); + updateDiagnostic(ctx, node, annotName, HttpDiagnosticCodes.HTTP_103); } private static void reportInvalidParameterAnnotation(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid annotation type on param '" + paramName + - "': expected one of the following types: 'http:Payload', 'http:CallerInfo', 'http:Headers'"; - reportError(ctx, node, msg, HTTP_104); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_104); } private static void reportInvalidParameter(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid resource parameter" + (paramName.isEmpty() ? "" : ": '" + paramName + "'"); - reportError(ctx, node, msg, HTTP_105); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_105); } private static void reportInvalidParameterType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String typeName) { - String msg = "invalid resource parameter type: '" + typeName + "'"; - reportError(ctx, node, msg, HTTP_106); + updateDiagnostic(ctx, node, typeName, HttpDiagnosticCodes.HTTP_106); } private static void reportInvalidPayloadParameterType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String typeName) { - String msg = "invalid payload parameter type: '" + typeName + "'"; - reportError(ctx, node, msg, HTTP_107); + updateDiagnostic(ctx, node, typeName, HttpDiagnosticCodes.HTTP_107); } private static void reportInvalidMultipleAnnotation(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid multiple resource parameter annotations for '" + paramName + - "': expected one of the following types: 'http:Payload', 'http:CallerInfo', 'http:Headers'"; - reportError(ctx, node, msg, HTTP_108); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_108); } private static void reportInvalidHeaderParameterType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid type of header param '" + paramName + "': expected 'string' or 'string[]'"; - reportError(ctx, node, msg, HTTP_109); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_109); } private static void reportInvalidUnionHeaderType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid union type of header param '" + paramName + "': a string or an array of a string can " + - "only be union with '()'. Eg: string|() or string[]|()"; - reportError(ctx, node, msg, HTTP_110); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_110); } private static void reportInvalidCallerParameterType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid type of caller param '" + paramName + "': expected 'http:Caller'"; - reportError(ctx, node, msg, HTTP_111); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_111); } private static void reportInvalidQueryParameterType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid type of query param '" + paramName + "': expected one of the 'string', 'int', 'float', " + - "'boolean', 'decimal' types or the array types of them"; - reportError(ctx, node, msg, HTTP_112); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_112); } private static void reportInvalidUnionQueryType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String paramName) { - String msg = "invalid union type of query param '" + paramName + "': 'string', 'int', 'float', 'boolean', " + - "'decimal' type or the array types of them can only be union with '()'. Eg: string? or int[]?"; - reportError(ctx, node, msg, HTTP_113); + updateDiagnostic(ctx, node, paramName, HttpDiagnosticCodes.HTTP_113); + } + + private static void updateDiagnostic(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, String returnType, + HttpDiagnosticCodes httpDiagnosticCodes) { + DiagnosticInfo diagnosticInfo = getDiagnosticInfo(httpDiagnosticCodes, returnType); + ctx.reportDiagnostic(DiagnosticFactory.createDiagnostic(diagnosticInfo, node.location())); } - private static void reportError(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node, - String errorMsg, String errorCode) { - DiagnosticInfo diagnosticInfo = new DiagnosticInfo(errorCode, errorMsg, ERROR); - ctx.reportDiagnostic( - DiagnosticFactory.createDiagnostic(diagnosticInfo, node.location(), node.functionName().toString())); + private static DiagnosticInfo getDiagnosticInfo(HttpDiagnosticCodes diagnostic, Object... args) { + return new DiagnosticInfo(diagnostic.getCode(), String.format(diagnostic.getMessage(), args), + diagnostic.getSeverity()); } } diff --git a/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpServiceValidator.java b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpServiceValidator.java index 4c908f2faf..d24e1498b4 100644 --- a/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpServiceValidator.java +++ b/http-compiler-plugin/src/main/java/io/ballerina/stdlib/http/compiler/HttpServiceValidator.java @@ -41,10 +41,8 @@ import static io.ballerina.stdlib.http.compiler.Constants.BALLERINA; import static io.ballerina.stdlib.http.compiler.Constants.HTTP; -import static io.ballerina.stdlib.http.compiler.Constants.HTTP_101; import static io.ballerina.stdlib.http.compiler.Constants.REMOTE_KEYWORD; -import static io.ballerina.stdlib.http.compiler.Constants.REMOTE_METHODS_NOT_ALLOWED; -import static io.ballerina.tools.diagnostics.DiagnosticSeverity.ERROR; +import static io.ballerina.stdlib.http.compiler.HttpDiagnosticCodes.HTTP_101; /** * Validates a Ballerina Http Service. @@ -100,7 +98,8 @@ private boolean isHttpModule(ModuleSymbol moduleSymbol) { } private void reportInvalidFunctionType(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode node) { - DiagnosticInfo diagnosticInfo = new DiagnosticInfo(HTTP_101, REMOTE_METHODS_NOT_ALLOWED, ERROR); + DiagnosticInfo diagnosticInfo = new DiagnosticInfo(HTTP_101.getCode(), HTTP_101.getMessage(), + HTTP_101.getSeverity()); ctx.reportDiagnostic(DiagnosticFactory.createDiagnostic(diagnosticInfo, node.location())); } }