diff --git a/ballerina/annotation.bal b/ballerina/annotation.bal index 1bb72981..385f2b9e 100644 --- a/ballerina/annotation.bal +++ b/ballerina/annotation.bal @@ -23,7 +23,7 @@ public type AZFunctionConfiguration record {| |}; public type AUTH_LEVEL "anonymous"|"function"|"admin"; -public const annotation HTTPTriggerConfiguration HttpTrigger on source listener; +public const annotation HTTPTriggerConfiguration HttpTrigger on source listener, service; # HTTPTrigger annotation configuration. # diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/FunctionArtifactTest.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/FunctionArtifactTest.java index 99ec8ce2..11935380 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/FunctionArtifactTest.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/FunctionArtifactTest.java @@ -75,7 +75,7 @@ public void compileSample() { DiagnosticResult diagnosticResult = compilation.diagnosticResult(); Assert.assertFalse(diagnosticResult.hasErrors()); - Assert.assertEquals(generatedFunctions.size(), 19); + Assert.assertEquals(generatedFunctions.size(), 24); } @Test @@ -89,6 +89,17 @@ public void testOptionalHttp() { Assert.assertEquals(httpHello, parse); } + @Test + public void testHttpTriggerInlineListener() { + JsonObject httpHello = generatedFunctions.get("post-helo-hello-query"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"helo/hello-query\"}," + + "{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(httpHello, parse); + } + @Test public void testHttpHello() { JsonObject httpHello = generatedFunctions.get("post-hello"); @@ -155,6 +166,18 @@ public void testQueueTrigger() { Assert.assertEquals(actual, parse); } + @Test + public void testQueueTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("queue1"); + String str = + "{\"bindings\":[{\"type\":\"queueTrigger\",\"connection\":\"AzureWebJobsStorage\"," + + "\"queueName\":\"queue21\",\"direction\":\"in\",\"name\":\"inMsg\"},{\"type\":\"queue\"," + + "\"connection\":\"AzureWebJobsStorage\",\"queueName\":\"queue3\",\"direction\":\"out\"," + + "\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + @Test public void testCosmosTrigger() { JsonObject actual = generatedFunctions.get("cosmos"); @@ -168,6 +191,19 @@ public void testCosmosTrigger() { Assert.assertEquals(actual, parse); } + @Test + public void testCosmosTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("cosmos1"); + String str = + "{\"bindings\":[{\"type\":\"cosmosDBTrigger\",\"connectionStringSetting\":\"CosmosDBConnection\"," + + "\"databaseName\":\"db1\",\"collectionName\":\"c2\",\"name\":\"inMsg\",\"direction\":\"in\"," + + "\"createLeaseCollectionIfNotExists\":true,\"leasesCollectionThroughput\":400}," + + "{\"type\":\"queue\",\"connection\":\"AzureWebJobsStorage\",\"queueName\":\"queue3\"," + + "\"direction\":\"out\",\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + @Test public void testTimerTrigger() { JsonObject actual = generatedFunctions.get("timer"); @@ -178,6 +214,16 @@ public void testTimerTrigger() { Assert.assertEquals(actual, parse); } + @Test + public void testTimerTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("timer1"); + String str = "{\"bindings\":[{\"type\":\"timerTrigger\",\"schedule\":\"*/10 * * * * *\"," + + "\"runOnStartup\":true,\"direction\":\"in\",\"name\":\"inMsg\"},{\"type\":\"queue\",\"connection\":" + + "\"AzureWebJobsStorage\",\"queueName\":\"queue3\",\"direction\":\"out\",\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + @Test public void testBlobTrigger() { JsonObject actual = generatedFunctions.get("blob"); @@ -189,6 +235,17 @@ public void testBlobTrigger() { Assert.assertEquals(actual, parse); } + @Test + public void testBlobTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("blob1"); + String str = "{\"bindings\":[{\"type\":\"blobTrigger\",\"name\":\"blobIn\",\"direction\":\"in\"," + + "\"path\":\"bpath1/{name}\",\"connection\":\"AzureWebJobsStorage\"},{\"type\":\"blob\"," + + "\"direction\":\"out\",\"name\":\"outMsg\",\"path\":\"bpath1/newBlob\"," + + "\"connection\":\"AzureWebJobsStorage\",\"dataType\":\"string\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + @Test public void testEscapeSequence() { JsonObject httpHello = generatedFunctions.get("post-hello--hello-query"); diff --git a/compiler-plugin-tests/src/test/resources/handlers/main.bal b/compiler-plugin-tests/src/test/resources/handlers/main.bal index 896bd071..f168e0af 100644 --- a/compiler-plugin-tests/src/test/resources/handlers/main.bal +++ b/compiler-plugin-tests/src/test/resources/handlers/main.bal @@ -21,6 +21,13 @@ service /hello\- on ep1 { } } +service /helo on new af:HttpListener() { + + resource function post hello\-query() returns string|error { + return "Hello from the hello-query"; + } +} + // @af:HTTPTest service /hello on ep { resource function default all() returns @af:HttpOutput string { @@ -94,6 +101,17 @@ service "queue" on queueListener { } } + +@af:QueueTrigger { + queueName: "queue21" +} +service "queue1" on new af:QueueListener() { + remote function onMessage (string inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo "+ inMsg; + } +} + + @af:CosmosDBTrigger {connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c2"} listener af:CosmosDBListener cosmosEp = new (); @@ -104,6 +122,16 @@ service "cosmos" on cosmosEp { } } + +@af:CosmosDBTrigger {connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c2"} +service "cosmos1" on new af:CosmosDBListener() { + remote function onUpdated (DBEntry[] inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + string id = inMsg[0].id; + return "helloo "+ id; + } +} + + @af:TimerTrigger { schedule: "*/10 * * * * *" } listener af:TimerListener timerListener = new af:TimerListener(); service "timer" on timerListener { @@ -112,6 +140,14 @@ service "timer" on timerListener { } } + +@af:TimerTrigger { schedule: "*/10 * * * * *" } +service "timer1" on new af:TimerListener() { + remote function onTrigger (af:TimerMetadata inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo "+ inMsg.IsPastDue.toString(); + } +} + @af:BlobTrigger { path: "bpath1/{name}" } @@ -123,3 +159,14 @@ service "blob" on blobListener { return blobIn; } } + +@af:BlobTrigger { + path: "bpath1/{name}" +} + +service "blob1" on new af:BlobListener() { + remote function onUpdated (byte[] blobIn, @af:BindingName { } string name) returns @af:BlobOutput { + path: "bpath1/newBlob" } byte[]|error { + return blobIn; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/TriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/TriggerBinding.java index 99da8b7e..cb79cc8f 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/TriggerBinding.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/TriggerBinding.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Optional; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.EXPLICIT_NEW_EXPRESSION; /** * Represents an Trigger Binding in Azure Functions. * @@ -37,18 +38,23 @@ public TriggerBinding(String triggerType) { public Optional getListenerAnnotation(ServiceDeclarationNode svcDeclNode, String annotationName) { //TODO handle inline decl for (ExpressionNode expression : svcDeclNode.expressions()) { - Optional symbol = this.semanticModel.symbol(expression); - if (symbol.isEmpty()) { - continue; - } - Symbol listenerSymbol = symbol.get(); - if (listenerSymbol.kind() != SymbolKind.VARIABLE) { - continue; + Optional metadata; + if (expression.kind() == EXPLICIT_NEW_EXPRESSION) { + metadata = svcDeclNode.metadata(); + } else { + Optional symbol = this.semanticModel.symbol(expression); + if (symbol.isEmpty()) { + continue; + } + Symbol listenerSymbol = symbol.get(); + if (listenerSymbol.kind() != SymbolKind.VARIABLE) { + continue; + } + VariableSymbol variableSymbol = (VariableSymbol) listenerSymbol; + ListenerDeclarationNode listenerDeclarationNode = + (ListenerDeclarationNode) Util.findNode(svcDeclNode, variableSymbol); + metadata = listenerDeclarationNode.metadata(); } - VariableSymbol variableSymbol = (VariableSymbol) listenerSymbol; - ListenerDeclarationNode listenerDeclarationNode = - (ListenerDeclarationNode) Util.findNode(svcDeclNode, variableSymbol); - Optional metadata = listenerDeclarationNode.metadata(); if (metadata.isEmpty()) { continue; } @@ -79,7 +85,6 @@ public Optional getListenerAnnotation(ServiceDeclarationNode svc // } // } } - return Optional.empty(); }