diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index 2128d83..150a879 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -5,7 +5,7 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.11.0-20241121-075100-c4c87cbc" +distribution-version = "2201.11.0-20250127-101700-a4b67fe5" [[package]] org = "ballerina" diff --git a/ballerina/tests/publish_subscribe_tests.bal b/ballerina/tests/publish_subscribe_tests.bal index 7738c65..5aafb8a 100644 --- a/ballerina/tests/publish_subscribe_tests.bal +++ b/ballerina/tests/publish_subscribe_tests.bal @@ -187,31 +187,30 @@ function publishSubscribeWithMTLSTrustKeyStoresTest() returns error? { test:assertTrue(receivedMessages.indexOf(message) != ()); } +listener Listener manualAcksListener = new (NO_AUTH_MTLS_ENDPOINT, uuid:createType1AsString(), "mqtt/manualackstopic", {connectionConfig: mtlsConnConfig, manualAcks: true}); + +service on manualAcksListener { + remote function onMessage(Message message, Caller caller) returns error? { + log:printInfo(check string:fromBytes(message.payload)); + receivedMessages.push(check string:fromBytes(message.payload)); + check caller->complete(); + } + remote function onError(Error err) returns error? { + log:printError("Error occured ", err); + } + remote function onComplete(DeliveryToken token) returns error? { + log:printInfo("Message delivered " + token.messageId.toString()); + } +}; + @test:Config {enable: true} function subscribeWithManualAcks() returns error? { - Listener 'listener = check new (NO_AUTH_MTLS_ENDPOINT, uuid:createType1AsString(), "mqtt/manualackstopic", {connectionConfig: mtlsConnConfig, manualAcks: true}); - Service manualAcksService = service object { - remote function onMessage(Message message, Caller caller) returns error? { - log:printInfo(check string:fromBytes(message.payload)); - receivedMessages.push(check string:fromBytes(message.payload)); - check caller->complete(); - } - remote function onError(Error err) returns error? { - log:printError("Error occured ", err); - } - remote function onComplete(DeliveryToken token) returns error? { - log:printInfo("Message delivered " + token.messageId.toString()); - } - }; - check 'listener.attach(manualAcksService); - check 'listener.'start(); - Client 'client = check new (NO_AUTH_MTLS_ENDPOINT, uuid:createType1AsString(), {connectionConfig: mtlsConnConfig}); string message = "Test message for manual acks"; _ = check 'client->publish("mqtt/manualackstopic", {payload: message.toBytes()}); runtime:sleep(1); - addListenerAndClientToArray('listener, 'client); + addListenerAndClientToArray(manualAcksListener, 'client); test:assertTrue(receivedMessages.indexOf(message) != ()); } diff --git a/changelog.md b/changelog.md index 329865a..576f579 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,12 @@ This file contains all the notable changes done to the Ballerina MQTT package th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed + +- [Allow onComplete method in the service declaration](https://github.com/ballerina-platform/ballerina-library/issues/7272) + ## [1.1.1] - 2024-07-17 ### Fixed diff --git a/compiler-plugin-tests/src/test/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidationTest.java b/compiler-plugin-tests/src/test/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidationTest.java index c3f71d2..1715ade 100644 --- a/compiler-plugin-tests/src/test/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidationTest.java +++ b/compiler-plugin-tests/src/test/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidationTest.java @@ -33,14 +33,17 @@ import static io.ballerina.stdlib.mqtt.compiler.CompilerPluginTestUtils.getEnvironmentBuilder; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.FUNCTION_SHOULD_BE_REMOTE; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_CALLER_PARAMETER; +import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_DELIVERY_TOKEN_PARAM_COUNT; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_MESSAGE_PARAMETER; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_MULTIPLE_LISTENERS; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_REMOTE_FUNCTION; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_RESOURCE_FUNCTION; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_RETURN_TYPE_ERROR_OR_NIL; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.MUST_HAVE_CALLER_AND_MESSAGE; +import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.MUST_HAVE_DELIVERY_TOKEN; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.MUST_HAVE_ERROR; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.NO_ON_MESSAGE; +import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.ONLY_DELIVERY_TOKEN_ALLOWED; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.ONLY_ERROR_ALLOWED; /** @@ -116,6 +119,14 @@ public void testValidService7() { Assert.assertEquals(diagnosticResult.errors().size(), 0); } + @Test(description = "Validate service with onMessage remote function") + public void testValidService8() { + Package currentPackage = loadPackage("valid_service_8"); + PackageCompilation compilation = currentPackage.getCompilation(); + DiagnosticResult diagnosticResult = compilation.diagnosticResult(); + Assert.assertEquals(diagnosticResult.errors().size(), 0); + } + @Test(enabled = true, description = "Service validating return types") public void testInvalidService1() { Package currentPackage = loadPackage("invalid_service_1"); @@ -273,4 +284,34 @@ public void testInvalidService14() { assertDiagnostic(diagnostic, INVALID_RESOURCE_FUNCTION); } } + + @Test(description = "Validate parameter in onComplete") + public void testInvalidService15() { + Package currentPackage = loadPackage("invalid_service_15"); + PackageCompilation compilation = currentPackage.getCompilation(); + DiagnosticResult diagnosticResult = compilation.diagnosticResult(); + Assert.assertEquals(diagnosticResult.errors().size(), 1); + Diagnostic diagnostic = (Diagnostic) diagnosticResult.errors().toArray()[0]; + assertDiagnostic(diagnostic, ONLY_DELIVERY_TOKEN_ALLOWED); + } + + @Test(description = "Validate parameter count in onComplete") + public void testInvalidService16() { + Package currentPackage = loadPackage("invalid_service_16"); + PackageCompilation compilation = currentPackage.getCompilation(); + DiagnosticResult diagnosticResult = compilation.diagnosticResult(); + Assert.assertEquals(diagnosticResult.errors().size(), 1); + Diagnostic diagnostic = (Diagnostic) diagnosticResult.errors().toArray()[0]; + assertDiagnostic(diagnostic, INVALID_DELIVERY_TOKEN_PARAM_COUNT); + } + + @Test(description = "Validate no delivery token parameter in onComplete") + public void testInvalidService17() { + Package currentPackage = loadPackage("invalid_service_17"); + PackageCompilation compilation = currentPackage.getCompilation(); + DiagnosticResult diagnosticResult = compilation.diagnosticResult(); + Assert.assertEquals(diagnosticResult.errors().size(), 1); + Diagnostic diagnostic = (Diagnostic) diagnosticResult.errors().toArray()[0]; + assertDiagnostic(diagnostic, MUST_HAVE_DELIVERY_TOKEN); + } } diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_15/Ballerina.toml b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_15/Ballerina.toml new file mode 100644 index 0000000..8b8bb0f --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_15/Ballerina.toml @@ -0,0 +1,4 @@ +[package] +org = "kafka_test" +name = "invalid_service_15" +version = "0.1.0" diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_15/service.bal b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_15/service.bal new file mode 100644 index 0000000..375e6fd --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_15/service.bal @@ -0,0 +1,40 @@ +// Copyright (c) 2025 WSO2 LLC. (https://www.wso2.com). +// +// 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 +// +// 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. + +import ballerina/mqtt; +import ballerina/uuid; + +mqtt:ListenerConfiguration listenerConfiguration = { + connectionConfig: { + username: "ballerina", + password: "ballerinamqtt" + }, + manualAcks: false +}; + +listener mqtt:Listener mqttSubscriber = check new (mqtt:DEFAULT_URL, uuid:createType1AsString(), "mqtt/test", listenerConfiguration); + +service on mqttSubscriber { + + private final string var1 = "Mqtt Service"; + private final int var2 = 54; + + remote function onMessage(mqtt:Message message) returns mqtt:Error? { + } + + remote function onComplete(record{} token) { + } +} diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_16/Ballerina.toml b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_16/Ballerina.toml new file mode 100644 index 0000000..7863a17 --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_16/Ballerina.toml @@ -0,0 +1,4 @@ +[package] +org = "kafka_test" +name = "invalid_service_16" +version = "0.1.0" diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_16/service.bal b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_16/service.bal new file mode 100644 index 0000000..e6f198c --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_16/service.bal @@ -0,0 +1,40 @@ +// Copyright (c) 2025 WSO2 LLC. (https://www.wso2.com). +// +// 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 +// +// 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. + +import ballerina/mqtt; +import ballerina/uuid; + +mqtt:ListenerConfiguration listenerConfiguration = { + connectionConfig: { + username: "ballerina", + password: "ballerinamqtt" + }, + manualAcks: false +}; + +listener mqtt:Listener mqttSubscriber = check new (mqtt:DEFAULT_URL, uuid:createType1AsString(), "mqtt/test", listenerConfiguration); + +service on mqttSubscriber { + + private final string var1 = "Mqtt Service"; + private final int var2 = 54; + + remote function onMessage(mqtt:Message message) returns mqtt:Error? { + } + + remote function onComplete(mqtt:DeliveryToken token, record{} data) { + } +} diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_17/Ballerina.toml b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_17/Ballerina.toml new file mode 100644 index 0000000..26636e0 --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_17/Ballerina.toml @@ -0,0 +1,4 @@ +[package] +org = "kafka_test" +name = "invalid_service_17" +version = "0.1.0" diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_17/service.bal b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_17/service.bal new file mode 100644 index 0000000..4cc232c --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/invalid_service_17/service.bal @@ -0,0 +1,40 @@ +// Copyright (c) 2025 WSO2 LLC. (https://www.wso2.com). +// +// 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 +// +// 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. + +import ballerina/mqtt; +import ballerina/uuid; + +mqtt:ListenerConfiguration listenerConfiguration = { + connectionConfig: { + username: "ballerina", + password: "ballerinamqtt" + }, + manualAcks: false +}; + +listener mqtt:Listener mqttSubscriber = check new (mqtt:DEFAULT_URL, uuid:createType1AsString(), "mqtt/test", listenerConfiguration); + +service on mqttSubscriber { + + private final string var1 = "Mqtt Service"; + private final int var2 = 54; + + remote function onMessage(mqtt:Message message) returns mqtt:Error? { + } + + remote function onComplete() { + } +} diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/valid_service_8/Ballerina.toml b/compiler-plugin-tests/src/test/resources/ballerina_sources/valid_service_8/Ballerina.toml new file mode 100644 index 0000000..b0957a7 --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/valid_service_8/Ballerina.toml @@ -0,0 +1,4 @@ +[package] +org = "kafka_test" +name = "valid_service_08" +version = "0.1.0" diff --git a/compiler-plugin-tests/src/test/resources/ballerina_sources/valid_service_8/service.bal b/compiler-plugin-tests/src/test/resources/ballerina_sources/valid_service_8/service.bal new file mode 100644 index 0000000..92f973a --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/ballerina_sources/valid_service_8/service.bal @@ -0,0 +1,61 @@ +// Copyright (c) 2025 WSO2 LLC. (https://www.wso2.com). +// +// 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 +// +// 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. + +import ballerina/mqtt; +import ballerina/uuid; + +mqtt:ListenerConfiguration listenerConfiguration = { + connectionConfig: { + username: "ballerina", + password: "ballerinamqtt" + }, + manualAcks: false +}; + +listener mqtt:Listener mqttSubscriber = check new (mqtt:DEFAULT_URL, uuid:createType1AsString(), "mqtt/test", listenerConfiguration); + +@display { + label: "mqttService1" +} +service on mqttSubscriber { + remote function onMessage(mqtt:Message message) returns mqtt:Error? { + } + + remote function onComplete(mqtt:DeliveryToken token) returns mqtt:Error? { + } +} + +@display { + label: "mqttService2" +} +service on mqttSubscriber { + remote function onMessage(mqtt:Message message) returns error? { + } + + remote function onComplete(mqtt:DeliveryToken token) returns error? { + } +} + +@display { + label: "mqttService3" +} +service on mqttSubscriber { + remote function onMessage(mqtt:Message message) { + } + + remote function onComplete(mqtt:DeliveryToken token) { + } +} diff --git a/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttFunctionValidator.java b/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttFunctionValidator.java index 4bc832b..ebb7e7c 100644 --- a/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttFunctionValidator.java +++ b/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttFunctionValidator.java @@ -45,14 +45,18 @@ import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CALLER; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.FUNCTION_SHOULD_BE_REMOTE; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_CALLER_PARAMETER; +import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_DELIVERY_TOKEN_PARAM_COUNT; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_ERROR_PARAM_COUNT; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_MESSAGE_PARAMETER; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_PARAM_COUNT; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.INVALID_RETURN_TYPE_ERROR_OR_NIL; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.MUST_HAVE_CALLER_AND_MESSAGE; +import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.MUST_HAVE_DELIVERY_TOKEN; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.MUST_HAVE_ERROR; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.NO_ON_MESSAGE; +import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.ONLY_DELIVERY_TOKEN_ALLOWED; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.CompilationErrors.ONLY_ERROR_ALLOWED; +import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.DELIVERY_TOKEN; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.ERROR_PARAM; import static io.ballerina.stdlib.mqtt.compiler.PluginConstants.MESSAGE; import static io.ballerina.stdlib.mqtt.compiler.PluginUtils.getDiagnostic; @@ -70,13 +74,15 @@ public class MqttFunctionValidator { private final SemanticModel semanticModel; private final FunctionDefinitionNode onMessage; private final FunctionDefinitionNode onError; + private final FunctionDefinitionNode onComplete; public MqttFunctionValidator(SyntaxNodeAnalysisContext context, FunctionDefinitionNode onMessage, - FunctionDefinitionNode onError) { + FunctionDefinitionNode onError, FunctionDefinitionNode onComplete) { this.context = context; this.serviceDeclarationNode = (ServiceDeclarationNode) context.node(); this.onMessage = onMessage; this.onError = onError; + this.onComplete = onComplete; this.semanticModel = context.semanticModel(); } @@ -85,6 +91,9 @@ public void validate() { if (Objects.nonNull(onError)) { validateOnError(); } + if (Objects.nonNull(onComplete)) { + validateOnComplete(); + } } private void validateMandatoryFunction() { @@ -111,6 +120,14 @@ private void validateOnError() { validateReturnTypeErrorOrNil(onError); } + private void validateOnComplete() { + if (!PluginUtils.isRemoteFunction(context, onComplete)) { + reportErrorDiagnostic(FUNCTION_SHOULD_BE_REMOTE, onComplete.location()); + } + validateOnCompleteParameters(onComplete); + validateReturnTypeErrorOrNil(onComplete); + } + private void validateOnErrorParameters(FunctionDefinitionNode functionDefinitionNode) { SeparatedNodeList parameters = functionDefinitionNode.functionSignature().parameters(); if (parameters.size() == 1) { @@ -122,6 +139,18 @@ private void validateOnErrorParameters(FunctionDefinitionNode functionDefinition } } + private void validateOnCompleteParameters(FunctionDefinitionNode functionDefinitionNode) { + SeparatedNodeList parameters = functionDefinitionNode.functionSignature().parameters(); + if (parameters.size() == 1) { + validateOnCompleteParameter(parameters.get(0)); + } else if (parameters.size() > 1) { + reportErrorDiagnostic(INVALID_DELIVERY_TOKEN_PARAM_COUNT, + functionDefinitionNode.functionSignature().location()); + } else { + reportErrorDiagnostic(MUST_HAVE_DELIVERY_TOKEN, functionDefinitionNode.functionSignature().location()); + } + } + private void validateErrorParameter(ParameterNode parameterNode) { SyntaxKind paramSyntaxKind = ((RequiredParameterNode) parameterNode).typeName().kind(); if (paramSyntaxKind.equals(QUALIFIED_NAME_REFERENCE)) { @@ -136,6 +165,20 @@ private void validateErrorParameter(ParameterNode parameterNode) { } } + private void validateOnCompleteParameter(ParameterNode parameterNode) { + SyntaxKind paramSyntaxKind = ((RequiredParameterNode) parameterNode).typeName().kind(); + if (paramSyntaxKind.equals(QUALIFIED_NAME_REFERENCE)) { + Node parameterTypeNode = ((RequiredParameterNode) parameterNode).typeName(); + Optional symbol = semanticModel.symbol(parameterTypeNode); + if (symbol.isPresent() && symbol.get().getName().isPresent() && + symbol.get().getName().get().equals(DELIVERY_TOKEN) && symbol.get().getModule().isPresent() && + validateModuleId(symbol.get().getModule().get())) { + return; + } + } + reportErrorDiagnostic(ONLY_DELIVERY_TOKEN_ALLOWED, parameterNode.location()); + } + private void validateOnMessageParameters(FunctionDefinitionNode functionDefinitionNode) { SeparatedNodeList parameters = functionDefinitionNode.functionSignature().parameters(); Location location = functionDefinitionNode.functionSignature().location(); diff --git a/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidator.java b/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidator.java index 36ad01c..3cd4082 100644 --- a/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidator.java +++ b/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/MqttServiceValidator.java @@ -57,6 +57,7 @@ public void validate(SyntaxNodeAnalysisContext context) { FunctionDefinitionNode onMessage = null; FunctionDefinitionNode onError = null; + FunctionDefinitionNode onComplete = null; for (Node node : memberNodes) { if (node.kind() == SyntaxKind.OBJECT_METHOD_DEFINITION) { @@ -68,6 +69,8 @@ public void validate(SyntaxNodeAnalysisContext context) { onMessage = functionDefinitionNode; } else if (functionName.get().equals(PluginConstants.ON_ERROR_FUNC)) { onError = functionDefinitionNode; + } else if (functionName.get().equals(PluginConstants.ON_COMPLETE_FUNC)) { + onComplete = functionDefinitionNode; } else if (PluginUtils.isRemoteFunction(context, functionDefinitionNode)) { context.reportDiagnostic(PluginUtils.getDiagnostic( PluginConstants.CompilationErrors.INVALID_REMOTE_FUNCTION, @@ -80,6 +83,6 @@ public void validate(SyntaxNodeAnalysisContext context) { DiagnosticSeverity.ERROR, node.location())); } } - new MqttFunctionValidator(context, onMessage, onError).validate(); + new MqttFunctionValidator(context, onMessage, onError, onComplete).validate(); } } diff --git a/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/PluginConstants.java b/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/PluginConstants.java index aebbd2a..7d444e0 100644 --- a/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/PluginConstants.java +++ b/compiler-plugin/src/main/java/io/ballerina/stdlib/mqtt/compiler/PluginConstants.java @@ -26,12 +26,14 @@ public class PluginConstants { public static final String PACKAGE_PREFIX = "mqtt"; public static final String ON_MESSAGE_FUNC = "onMessage"; public static final String ON_ERROR_FUNC = "onError"; + public static final String ON_COMPLETE_FUNC = "onComplete"; public static final String PACKAGE_ORG = "ballerina"; // parameters public static final String CALLER = "Caller"; public static final String MESSAGE = "Message"; public static final String ERROR_PARAM = "Error"; + public static final String DELIVERY_TOKEN = "DeliveryToken"; // return types error or nil public static final String BALLERINA_ERROR = "error"; @@ -63,7 +65,11 @@ public enum CompilationErrors { MUST_HAVE_ERROR("Must have the required parameter mqtt:Error", "MQTT_111"), INVALID_ERROR_PARAM_COUNT("Invalid method parameter count. Only mqtt:Error is allowed.", "MQTT_112"), ONLY_ERROR_ALLOWED("Invalid method parameter. Only mqtt:Error or error is allowed", "MQTT_113"), - TEMPLATE_CODE_GENERATION_HINT("Template generation for empty service", "MQTT_114"); + TEMPLATE_CODE_GENERATION_HINT("Template generation for empty service", "MQTT_114"), + ONLY_DELIVERY_TOKEN_ALLOWED("Invalid method parameter. Only mqtt:DeliveryToken is allowed", "MQTT_115"), + INVALID_DELIVERY_TOKEN_PARAM_COUNT("Invalid method parameter count. Only mqtt:DeliveryToken is allowed", + "MQTT_116"), + MUST_HAVE_DELIVERY_TOKEN("Must have the required parameter mqtt:DeliveryToken", "MQTT_117"); private final String error; private final String errorCode;