From a08d0a1595019015ba2b0006288887b2a16bdea7 Mon Sep 17 00:00:00 2001 From: pasindufernando1 Date: Thu, 12 Feb 2026 10:46:40 +0530 Subject: [PATCH 1/4] Address duplicate connection name in nodeTemplate --- .../core/model/NodeBuilder.java | 14 + .../core/model/node/NewConnectionBuilder.java | 9 + .../config/new_duplicate_connection.json | 854 ++++++++++++++++++ .../source/duplicate_connector/Ballerina.toml | 8 + .../duplicate_connector/connections.bal | 3 + 5 files changed, 888 insertions(+) create mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json create mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml create mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal diff --git a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/NodeBuilder.java b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/NodeBuilder.java index 166afe6c40..05cca5c3c3 100644 --- a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/NodeBuilder.java +++ b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/NodeBuilder.java @@ -319,5 +319,19 @@ public Set getAllVisibleSymbolNames() { return new HashSet<>(); } } + + public Set getAllModuleSymbolNames() { + try { + workspaceManager.loadProject(filePath); + SemanticModel semanticModel = + workspaceManager.semanticModel(filePath).orElseThrow(); + return semanticModel.moduleSymbols().parallelStream() + .filter(s -> s.getName().isPresent()) + .map(s -> s.getName().get()) + .collect(Collectors.toSet()); + } catch (Throwable e) { + return new HashSet<>(); + } + } } } diff --git a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/node/NewConnectionBuilder.java b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/node/NewConnectionBuilder.java index 7c8e9e1bad..33a5f91bf2 100644 --- a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/node/NewConnectionBuilder.java +++ b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/node/NewConnectionBuilder.java @@ -185,6 +185,15 @@ public void setConcreteTemplateData(TemplateContext context) { .checkError(true, CHECK_ERROR_DOC, false); } + @Override + protected void setReturnTypeProperties(FunctionData functionData, TemplateContext context, String label, String doc, + boolean hidden) { + properties() + .type(functionData.returnType(), false, functionData.importStatements(), hidden, + Property.RESULT_TYPE_LABEL) + .data(functionData.returnType(), context.getAllModuleSymbolNames(), label, doc); + } + protected void setParameterProperties(FunctionData function) { boolean hasOnlyRestParams = function.parameters().size() == 1; diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json new file mode 100644 index 0000000000..e7c278175b --- /dev/null +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json @@ -0,0 +1,854 @@ +{ + "source": "duplicate_connector/connections.bal", + "description": "Duplicate connection", + "codedata": { + "node": "NEW_CONNECTION", + "org": "ballerina", + "module": "http", + "packageName": "http", + "object": "Client", + "symbol": "init", + "version": "2.14.7", + "isGenerated": false + }, + "output": { + "id": "31", + "metadata": { + "label": "HTTP", + "description": "The HTTP client provides functionality to connect to remote HTTP services and perform requests using standard HTTP methods like GET, POST, PUT, DELETE, etc.\n", + "icon": "https://bcentral-packageicons.azureedge.net/images/ballerina_http_2.14.7.png" + }, + "codedata": { + "node": "NEW_CONNECTION", + "org": "ballerina", + "module": "http", + "packageName": "http", + "object": "Client", + "symbol": "init", + "version": "2.14.7", + "isNew": true, + "isGenerated": false + }, + "returning": false, + "properties": { + "url": { + "metadata": { + "label": "Url", + "description": "URL of the target service" + }, + "types": [ + { + "fieldType": "TEXT", + "ballerinaType": "string", + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "string", + "selected": false + } + ], + "placeholder": "\"\"", + "optional": false, + "editable": true, + "advanced": false, + "hidden": false, + "codedata": { + "kind": "REQUIRED", + "originalName": "url" + } + }, + "httpVersion": { + "metadata": { + "label": "HTTP Version", + "description": "HTTP protocol version supported by the client" + }, + "types": [ + { + "fieldType": "SINGLE_SELECT", + "options": [ + { + "label": "2.0", + "value": "\"2.0\"" + }, + { + "label": "1.1", + "value": "\"1.1\"" + }, + { + "label": "1.0", + "value": "\"1.0\"" + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:HttpVersion", + "selected": false + } + ], + "placeholder": "\"2.0\"", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "httpVersion" + }, + "defaultValue": "\"2.0\"" + }, + "http1Settings": { + "metadata": { + "label": "HTTP1 Settings", + "description": "HTTP/1.x specific settings" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:ClientHttp1Settings", + "typeMembers": [ + { + "type": "ClientHttp1Settings", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:ClientHttp1Settings", + "selected": false + } + ], + "placeholder": "{}", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "http1Settings" + }, + "defaultValue": "{}" + }, + "http2Settings": { + "metadata": { + "label": "HTTP2 Settings", + "description": "HTTP/2 specific settings" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:ClientHttp2Settings", + "typeMembers": [ + { + "type": "ClientHttp2Settings", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:ClientHttp2Settings", + "selected": false + } + ], + "placeholder": "{}", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "http2Settings" + }, + "defaultValue": "{}" + }, + "timeout": { + "metadata": { + "label": "Timeout", + "description": "Maximum time(in seconds) to wait for a response before the request times out" + }, + "types": [ + { + "fieldType": "NUMBER", + "ballerinaType": "decimal", + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "decimal", + "selected": false + } + ], + "placeholder": "0.0d", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "timeout" + }, + "defaultValue": "0.0d" + }, + "forwarded": { + "metadata": { + "label": "Forwarded", + "description": "The choice of setting `Forwarded`/`X-Forwarded-For` header, when acting as a proxy" + }, + "types": [ + { + "fieldType": "TEXT", + "ballerinaType": "string", + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "string", + "selected": false + } + ], + "placeholder": "\"\"", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "forwarded" + }, + "defaultValue": "\"\"" + }, + "followRedirects": { + "metadata": { + "label": "Follow Redirects", + "description": "HTTP redirect handling configurations (with 3xx status codes)" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:FollowRedirects", + "typeMembers": [ + { + "type": "FollowRedirects", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:FollowRedirects?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "followRedirects" + }, + "defaultValue": "()" + }, + "poolConfig": { + "metadata": { + "label": "Pool Config", + "description": "Configurations associated with the request connection pool" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:PoolConfiguration", + "typeMembers": [ + { + "type": "PoolConfiguration", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:PoolConfiguration?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "poolConfig" + }, + "defaultValue": "()" + }, + "cache": { + "metadata": { + "label": "Cache", + "description": "HTTP response caching related configurations" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:CacheConfig", + "typeMembers": [ + { + "type": "CacheConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:CacheConfig", + "selected": false + } + ], + "placeholder": "{}", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "cache" + }, + "defaultValue": "{}" + }, + "compression": { + "metadata": { + "label": "Compression", + "description": "Enable request/response compression (using `accept-encoding` header)" + }, + "types": [ + { + "fieldType": "SINGLE_SELECT", + "options": [ + { + "label": "AUTO", + "value": "\"AUTO\"" + }, + { + "label": "ALWAYS", + "value": "\"ALWAYS\"" + }, + { + "label": "NEVER", + "value": "\"NEVER\"" + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:Compression", + "selected": false + } + ], + "placeholder": "\"AUTO\"", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "compression" + }, + "defaultValue": "\"AUTO\"" + }, + "auth": { + "metadata": { + "label": "Auth", + "description": "Client authentication options (Basic, Bearer token, OAuth, etc.)" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:CredentialsConfig|http:BearerTokenConfig|http:JwtIssuerConfig|http:OAuth2ClientCredentialsGrantConfig|http:OAuth2PasswordGrantConfig|http:OAuth2RefreshTokenGrantConfig|http:OAuth2JwtBearerGrantConfig", + "typeMembers": [ + { + "type": "CredentialsConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + }, + { + "type": "BearerTokenConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + }, + { + "type": "JwtIssuerConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + }, + { + "type": "OAuth2ClientCredentialsGrantConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + }, + { + "type": "OAuth2PasswordGrantConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + }, + { + "type": "OAuth2RefreshTokenGrantConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + }, + { + "type": "OAuth2JwtBearerGrantConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:ClientAuthConfig?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "auth" + }, + "defaultValue": "()" + }, + "circuitBreaker": { + "metadata": { + "label": "Circuit Breaker", + "description": "Circuit breaker configurations to prevent cascading failures" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:CircuitBreakerConfig", + "typeMembers": [ + { + "type": "CircuitBreakerConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:CircuitBreakerConfig?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "circuitBreaker" + }, + "defaultValue": "()" + }, + "retryConfig": { + "metadata": { + "label": "Retry Config", + "description": "Automatic retry settings for failed requests" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:RetryConfig", + "typeMembers": [ + { + "type": "RetryConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:RetryConfig?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "retryConfig" + }, + "defaultValue": "()" + }, + "cookieConfig": { + "metadata": { + "label": "Cookie Config", + "description": "Cookie handling settings for session management" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:CookieConfig", + "typeMembers": [ + { + "type": "CookieConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:CookieConfig?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "cookieConfig" + }, + "defaultValue": "()" + }, + "responseLimits": { + "metadata": { + "label": "Response Limits", + "description": "Limits for response size and headers (to prevent memory issues)" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:ResponseLimitConfigs", + "typeMembers": [ + { + "type": "ResponseLimitConfigs", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:ResponseLimitConfigs", + "selected": false + } + ], + "placeholder": "{}", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "responseLimits" + }, + "defaultValue": "{}" + }, + "proxy": { + "metadata": { + "label": "Proxy", + "description": "Proxy server settings if requests need to go through a proxy" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:ProxyConfig", + "typeMembers": [ + { + "type": "ProxyConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:ProxyConfig?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "proxy" + }, + "defaultValue": "()" + }, + "validation": { + "metadata": { + "label": "Validation", + "description": "Enable automatic payload validation for request/response data against constraints" + }, + "types": [ + { + "fieldType": "FLAG", + "ballerinaType": "boolean", + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "boolean", + "selected": false + } + ], + "placeholder": "false", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "validation" + }, + "defaultValue": "false" + }, + "socketConfig": { + "metadata": { + "label": "Socket Config", + "description": "Low-level socket settings (timeouts, buffer sizes, etc.)" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:ClientSocketConfig", + "typeMembers": [ + { + "type": "ClientSocketConfig", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:ClientSocketConfig", + "selected": false + } + ], + "placeholder": "{}", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "socketConfig" + }, + "defaultValue": "{}" + }, + "laxDataBinding": { + "metadata": { + "label": "Lax Data Binding", + "description": "Enable relaxed data binding on the client side.\nWhen enabled:\n- `null` values in JSON are allowed to be mapped to optional fields\n- missing fields in JSON are allowed to be mapped as `null` values" + }, + "types": [ + { + "fieldType": "FLAG", + "ballerinaType": "boolean", + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "boolean", + "selected": false + } + ], + "placeholder": "false", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "laxDataBinding" + }, + "defaultValue": "false" + }, + "secureSocket": { + "metadata": { + "label": "Secure Socket", + "description": "SSL/TLS security settings for HTTPS connections" + }, + "types": [ + { + "fieldType": "RECORD_MAP_EXPRESSION", + "ballerinaType": "http:ClientSecureSocket", + "typeMembers": [ + { + "type": "ClientSecureSocket", + "packageInfo": "ballerina:http:2.14.7", + "packageName": "http", + "kind": "RECORD_TYPE", + "selected": false + } + ], + "selected": false + }, + { + "fieldType": "EXPRESSION", + "ballerinaType": "http:ClientSecureSocket?", + "selected": false + } + ], + "placeholder": "()", + "optional": true, + "editable": true, + "advanced": true, + "hidden": false, + "codedata": { + "kind": "INCLUDED_FIELD", + "originalName": "secureSocket" + }, + "defaultValue": "()" + }, + "type": { + "metadata": { + "label": "Result Type", + "description": "Type of the variable" + }, + "types": [ + { + "fieldType": "TYPE", + "selected": true + } + ], + "value": "http:Client", + "placeholder": "var", + "optional": false, + "editable": false, + "advanced": false, + "hidden": true, + "codedata": {}, + "imports": { + "http": "ballerina/http" + } + }, + "variable": { + "metadata": { + "label": "Connection Name", + "description": "Name of the connection" + }, + "types": [ + { + "fieldType": "IDENTIFIER", + "selected": true + } + ], + "value": "httpClientResult", + "optional": false, + "editable": true, + "advanced": false, + "hidden": false + }, + "scope": { + "metadata": { + "label": "Connection Scope", + "description": "Scope of the connection, Global or Local" + }, + "types": [ + { + "fieldType": "ENUM", + "selected": true + } + ], + "value": "Global", + "optional": false, + "editable": true, + "advanced": true, + "hidden": true + }, + "checkError": { + "metadata": { + "label": "Check Error", + "description": "Terminate on error" + }, + "types": [ + { + "fieldType": "FLAG", + "selected": true + } + ], + "value": true, + "optional": false, + "editable": false, + "advanced": true, + "hidden": true + } + }, + "flags": 0 + } +} diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml new file mode 100644 index 0000000000..a5fb1422f7 --- /dev/null +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "pasinduf" +name = "dup_connection1" +version = "0.1.0" +distribution = "2201.12.10" + +[build-options] +observabilityIncluded = true diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal new file mode 100644 index 0000000000..f4cb4fc61a --- /dev/null +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal @@ -0,0 +1,3 @@ +import ballerina/http; + +final http:Client httpClient = check new ("\"\""); From b38645b17dc23e55a848043d72ee25a0d8c68815 Mon Sep 17 00:00:00 2001 From: pasindufernando1 Date: Mon, 16 Feb 2026 11:04:16 +0530 Subject: [PATCH 2/4] Reuse existing test package --- .../node_template/config/new_duplicate_connection.json | 4 ++-- .../source/duplicate_connector/Ballerina.toml | 8 -------- .../source/duplicate_connector/connections.bal | 3 --- 3 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml delete mode 100644 flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json index e7c278175b..e4d9970e10 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json @@ -1,5 +1,5 @@ { - "source": "duplicate_connector/connections.bal", + "source": "local_connector/main.bal", "description": "Duplicate connection", "codedata": { "node": "NEW_CONNECTION", @@ -808,7 +808,7 @@ "selected": true } ], - "value": "httpClientResult", + "value": "httpClientOut", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml deleted file mode 100644 index a5fb1422f7..0000000000 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/Ballerina.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -org = "pasinduf" -name = "dup_connection1" -version = "0.1.0" -distribution = "2201.12.10" - -[build-options] -observabilityIncluded = true diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal deleted file mode 100644 index f4cb4fc61a..0000000000 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/source/duplicate_connector/connections.bal +++ /dev/null @@ -1,3 +0,0 @@ -import ballerina/http; - -final http:Client httpClient = check new ("\"\""); From 2ac7a0dcf3ef2fa41476ab353c89e18362ba9d00 Mon Sep 17 00:00:00 2001 From: pasindufernando1 Date: Tue, 17 Feb 2026 14:53:17 +0530 Subject: [PATCH 3/4] Refactor duplicate name renaming logic --- .../config/function_call-json-toJson.json | 2 +- .../config/function_call-user-union.json | 2 +- .../config/function_call-user.json | 2 +- .../config/function_call-userEscaped.json | 2 +- .../config/function_call-workspace1.json | 2 +- .../config/function_call-workspace2.json | 2 +- .../config/lang_lib-array-lastIndexOf.json | 2 +- .../config/method_call_user.json | 2 +- .../config/new_connection-http.json | 2 +- .../config/new_duplicate_connection.json | 2 +- .../np_functions/np_function_call_1.json | 2 +- .../np_functions/np_function_call_2.json | 2 +- ...mote_action_call-customclient-getData.json | 2 +- .../config/remote_action_call-redis-get.json | 2 +- .../config/remote_action_call-redis-set.json | 2 +- ...resource_action_call-customclient-get.json | 2 +- .../langserver/common/utils/NameUtil.java | 42 +------------------ 17 files changed, 17 insertions(+), 57 deletions(-) diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-json-toJson.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-json-toJson.json index 3f812796f1..03d977cc45 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-json-toJson.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-json-toJson.json @@ -83,7 +83,7 @@ "selected": true } ], - "value": "jsonResult", + "value": "json1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user-union.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user-union.json index 6dabdc4ab0..cd29d2c714 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user-union.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user-union.json @@ -224,7 +224,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user.json index 8451e3641e..7063054df3 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-user.json @@ -85,7 +85,7 @@ "selected": true } ], - "value": "intResult", + "value": "int1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-userEscaped.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-userEscaped.json index d8ff5a2490..25c00d353f 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-userEscaped.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-userEscaped.json @@ -189,7 +189,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace1.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace1.json index edb6a7f90b..655b8f9858 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace1.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace1.json @@ -83,7 +83,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace2.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace2.json index b4832cb339..86855aa2d3 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace2.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/function_call-workspace2.json @@ -83,7 +83,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/lang_lib-array-lastIndexOf.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/lang_lib-array-lastIndexOf.json index f2998ddafc..06c1245232 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/lang_lib-array-lastIndexOf.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/lang_lib-array-lastIndexOf.json @@ -133,7 +133,7 @@ "selected": true } ], - "value": "intResult", + "value": "int1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/method_call_user.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/method_call_user.json index 6e0be0a97f..05fab33e8c 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/method_call_user.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/method_call_user.json @@ -106,7 +106,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_connection-http.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_connection-http.json index 5a01c4fee3..29a0bff3f5 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_connection-http.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_connection-http.json @@ -810,7 +810,7 @@ "selected": true } ], - "value": "httpClientOut", + "value": "httpClient1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json index e4d9970e10..7a9bc3d114 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/new_duplicate_connection.json @@ -808,7 +808,7 @@ "selected": true } ], - "value": "httpClientOut", + "value": "httpClient1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_1.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_1.json index 23ca4c6ae2..4b073c8f10 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_1.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_1.json @@ -111,7 +111,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_2.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_2.json index 2ccd7ca5e2..51c5eeac4a 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_2.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/np_functions/np_function_call_2.json @@ -85,7 +85,7 @@ "selected": true } ], - "value": "intResult", + "value": "int1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-customclient-getData.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-customclient-getData.json index 131cfc20c6..94de5c3b91 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-customclient-getData.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-customclient-getData.json @@ -108,7 +108,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-get.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-get.json index 84b7b3f4a8..bfe06d847b 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-get.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-get.json @@ -109,7 +109,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-set.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-set.json index a4efdb0a0f..4156b340d8 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-set.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/remote_action_call-redis-set.json @@ -136,7 +136,7 @@ "selected": true } ], - "value": "stringResult", + "value": "string1", "optional": false, "editable": true, "advanced": false, diff --git a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/resource_action_call-customclient-get.json b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/resource_action_call-customclient-get.json index 7e62ecf253..bb54cbb55a 100644 --- a/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/resource_action_call-customclient-get.json +++ b/flow-model-generator/modules/flow-model-generator-ls-extension/src/test/resources/node_template/config/resource_action_call-customclient-get.json @@ -128,7 +128,7 @@ "selected": true } ], - "value": "jsonResult", + "value": "json1", "optional": false, "editable": true, "advanced": false, diff --git a/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java b/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java index f4ef51133c..180f150f0c 100644 --- a/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java +++ b/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java @@ -347,47 +347,7 @@ private static String generateVariableName(int suffix, String name, Set } // Lower first letter newName = newName.substring(0, 1).toLowerCase(Locale.getDefault()) + newName.substring(1); - // if already available, try appending 'Result', 'Out', 'Value' - boolean alreadyExists = false; - String[] specialSuffixes = new String[]{"Result", "Out", "Value"}; - boolean[] flagSpecialSuffixes = new boolean[specialSuffixes.length]; - boolean addNoSpecialSuffix = false; - // If any of special suffix already found in new-name, don't use any special suffix - for (String currentSuffix : specialSuffixes) { - if (newName.endsWith(currentSuffix)) { - addNoSpecialSuffix = true; - break; - } - } - for (String nextName : names) { - if (nextName.equals(newName)) { - // If new-name already exists - alreadyExists = true; - } else if (!addNoSpecialSuffix) { - // Check a particular special suffix and new-name combination already exists - for (int i = 0; i < specialSuffixes.length; i++) { - String currentSuffix = specialSuffixes[i]; - if (nextName.equals(newName + currentSuffix)) { - flagSpecialSuffixes[i] = true; - } - } - } - } - // if already available, try appending 'Result' or 'Out' - if (alreadyExists) { - if (!addNoSpecialSuffix) { - for (int i = 0; i < flagSpecialSuffixes.length; i++) { - if (!flagSpecialSuffixes[i]) { - newName = newName + specialSuffixes[i]; - break; - } - } - } else { - return generateVariableName(++suffix, newName, names); - } - } - } else { - newName = newName + suffix; + newName = generateTypeName(newName, names); } // if still already available, try a random letter while (names.contains(newName)) { From 871e02eff60092824b41cd5b4f6df7e91d67a42b Mon Sep 17 00:00:00 2001 From: pasindufernando1 Date: Tue, 17 Feb 2026 15:30:32 +0530 Subject: [PATCH 4/4] Make minor refactoring --- .../core/model/FormBuilder.java | 4 +- .../langserver/common/utils/NameUtil.java | 42 ++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/FormBuilder.java b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/FormBuilder.java index a2f92ccf56..00a7f57e51 100644 --- a/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/FormBuilder.java +++ b/flow-model-generator/modules/flow-model-generator-core/src/main/java/io/ballerina/flowmodelgenerator/core/model/FormBuilder.java @@ -127,7 +127,7 @@ public FormBuilder data(Node node, String label, String doc, String templateN public FormBuilder data(String typeSignature, Set names, String label) { String varName = typeSignature.contains(RemoteActionCallBuilder.TARGET_TYPE_KEY) ? NameUtil.generateTypeName("var", names) - : NameUtil.generateVariableName(typeSignature, names); + : NameUtil.generateTypeName(NameUtil.toCamelCase(typeSignature), names); propertyBuilder .metadata() .label(label) @@ -146,7 +146,7 @@ public FormBuilder data(String typeSignature, Set names, String label public FormBuilder data(String typeSignature, Set names, String label, String doc) { String varName = typeSignature.contains(RemoteActionCallBuilder.TARGET_TYPE_KEY) ? NameUtil.generateTypeName("var", names) - : NameUtil.generateVariableName(typeSignature, names); + : NameUtil.generateTypeName(NameUtil.toCamelCase(typeSignature), names); propertyBuilder .metadata() .label(label) diff --git a/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java b/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java index 180f150f0c..f4ef51133c 100644 --- a/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java +++ b/langserver-core/src/main/java/org/ballerinalang/langserver/common/utils/NameUtil.java @@ -347,7 +347,47 @@ private static String generateVariableName(int suffix, String name, Set } // Lower first letter newName = newName.substring(0, 1).toLowerCase(Locale.getDefault()) + newName.substring(1); - newName = generateTypeName(newName, names); + // if already available, try appending 'Result', 'Out', 'Value' + boolean alreadyExists = false; + String[] specialSuffixes = new String[]{"Result", "Out", "Value"}; + boolean[] flagSpecialSuffixes = new boolean[specialSuffixes.length]; + boolean addNoSpecialSuffix = false; + // If any of special suffix already found in new-name, don't use any special suffix + for (String currentSuffix : specialSuffixes) { + if (newName.endsWith(currentSuffix)) { + addNoSpecialSuffix = true; + break; + } + } + for (String nextName : names) { + if (nextName.equals(newName)) { + // If new-name already exists + alreadyExists = true; + } else if (!addNoSpecialSuffix) { + // Check a particular special suffix and new-name combination already exists + for (int i = 0; i < specialSuffixes.length; i++) { + String currentSuffix = specialSuffixes[i]; + if (nextName.equals(newName + currentSuffix)) { + flagSpecialSuffixes[i] = true; + } + } + } + } + // if already available, try appending 'Result' or 'Out' + if (alreadyExists) { + if (!addNoSpecialSuffix) { + for (int i = 0; i < flagSpecialSuffixes.length; i++) { + if (!flagSpecialSuffixes[i]) { + newName = newName + specialSuffixes[i]; + break; + } + } + } else { + return generateVariableName(++suffix, newName, names); + } + } + } else { + newName = newName + suffix; } // if still already available, try a random letter while (names.contains(newName)) {