From 00720d6909c319fec73c5021c2ac243bf4d8c26d Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Tue, 29 Nov 2022 11:11:01 +0100 Subject: [PATCH 01/11] Choice EIP short implementation --- .../internal/CamelTextDocumentService.java | 32 +++++-- .../lsp/internal/parser/CamelEIPParser.java | 51 +++++++++++ .../internal/parser/ParserFileHelperUtil.java | 22 +++++ .../eip/EIPChoiceCompletionTest.java | 88 +++++++++++++++++++ .../lsp/internal/util/RouteTextBuilder.java | 84 ++++++++++++++++++ 5 files changed, 272 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java create mode 100644 src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java diff --git a/src/main/java/com/github/cameltooling/lsp/internal/CamelTextDocumentService.java b/src/main/java/com/github/cameltooling/lsp/internal/CamelTextDocumentService.java index 2d4f9fce..0dccc2e4 100644 --- a/src/main/java/com/github/cameltooling/lsp/internal/CamelTextDocumentService.java +++ b/src/main/java/com/github/cameltooling/lsp/internal/CamelTextDocumentService.java @@ -19,11 +19,14 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; import com.github.cameltooling.lsp.internal.completion.modeline.CamelKModelineInsertionProcessor; +import com.github.cameltooling.lsp.internal.parser.CamelEIPParser; import com.github.cameltooling.lsp.internal.parser.CamelKModelineInsertionParser; import org.apache.camel.catalog.CamelCatalog; import org.apache.camel.catalog.DefaultCamelCatalog; @@ -161,15 +164,34 @@ public CompletableFuture, CompletionList>> completio TextDocumentItem textDocumentItem = openedDocuments.get(uri); if (textDocumentItem != null) { - if (uri.endsWith(".properties")){ + if (uri.endsWith(".properties")) { return new CamelPropertiesCompletionProcessor(textDocumentItem, getCamelCatalog(), getCamelKafkaConnectorManager()).getCompletions(completionParams.getPosition(), getSettingsManager(), getKameletsCatalogManager()).thenApply(Either::forLeft); - } else if (new CamelKModelineInsertionParser(textDocumentItem).canPutCamelKModeline(completionParams.getPosition())){ - return new CamelKModelineInsertionProcessor(textDocumentItem).getCompletions().thenApply(Either::forLeft); + } + + List>> completions = new LinkedList<>(); + + if (new CamelEIPParser(textDocumentItem).canPutEIP(completionParams.getPosition())){ + completions.add(new CamelEIPParser(textDocumentItem).getCompletions()); + } + + if (new CamelKModelineInsertionParser(textDocumentItem).canPutCamelKModeline(completionParams.getPosition())){ + completions.add(new CamelKModelineInsertionProcessor(textDocumentItem).getCompletions()); } else if (new CamelKModelineParser().isOnCamelKModeline(completionParams.getPosition().getLine(), textDocumentItem)){ - return new CamelKModelineCompletionprocessor(textDocumentItem, getCamelCatalog()).getCompletions(completionParams.getPosition()).thenApply(Either::forLeft); + completions.add(new CamelKModelineCompletionprocessor(textDocumentItem, getCamelCatalog()).getCompletions(completionParams.getPosition())); } else { - return new CamelEndpointCompletionProcessor(textDocumentItem, getCamelCatalog(), getKameletsCatalogManager()).getCompletions(completionParams.getPosition(), getSettingsManager()).thenApply(Either::forLeft); + completions.add(new CamelEndpointCompletionProcessor(textDocumentItem, getCamelCatalog(), getKameletsCatalogManager()).getCompletions(completionParams.getPosition(), getSettingsManager())); } + + //Combining all completable futures completion lists + //Source: https://nurkiewicz.com/2013/05/java-8-completablefuture-in-action.html + return CompletableFuture + .allOf(completions.toArray(new CompletableFuture[completions.size()])) + .thenApply( + v -> completions.stream() + .map(future -> future.join()) + .flatMap(x -> x.stream()) + .collect(Collectors.toList()) + ).thenApply(Either::forLeft); } else { LOGGER.warn("The document with uri {} has not been found in opened documents. Cannot provide completion.", uri); return CompletableFuture.completedFuture(Either.forLeft(Collections.emptyList())); diff --git a/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java new file mode 100644 index 00000000..93af45e7 --- /dev/null +++ b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java @@ -0,0 +1,51 @@ +package com.github.cameltooling.lsp.internal.parser; + +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.Position; +import org.eclipse.lsp4j.TextDocumentItem; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.regex.Pattern; + +public class CamelEIPParser { + + private final TextDocumentItem document; + + public CamelEIPParser(TextDocumentItem textDocumentItem) { + this.document = textDocumentItem; + } + + public boolean canPutEIP(Position position) { + Pattern CHOICE_EIP_PATTERN = Pattern.compile("\\)\\s*.?c?h?o?i?c?e?\\(?$", Pattern.MULTILINE); + ParserFileHelperUtil util = new ParserFileHelperUtil(); + String textUntilPosition = util.getTextUntilPosition(document, position); + + return CHOICE_EIP_PATTERN.matcher(textUntilPosition).find(); + } + + public CompletableFuture> getCompletions() { + return CompletableFuture.completedFuture( + List.of(choiceEIPcompletion()) + ); + } + + private CompletionItem choiceEIPcompletion() { + String newLine = System.getProperty("line.separator"); + CompletionItem completion = new CompletionItem("Content Based Router"); + completion.setDocumentation( + "Read more: https://camel.apache.org/components/3.11.x/eips/content-based-router-eip.html" + ); + completion.setInsertText( + ".choice()" + newLine + + ".when()" + newLine + + ".to()" + newLine + + ".when()" + newLine + + ".to()" + newLine + + ".otherwise()" + newLine + + ".to()" + ); + + return completion; + } +} diff --git a/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java b/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java index b35de381..4a249fd9 100644 --- a/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java +++ b/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java @@ -36,5 +36,27 @@ public String getLine(String text, int line) { } return null; } + + public String getTextUntilPosition(TextDocumentItem document, Position position) { + String newLine = System.getProperty("line.separator"); + String[] lines = document.getText().split(newLine); + String textUntilPosition = ""; + + if(document.getText().startsWith(newLine)) { + textUntilPosition += newLine; + } + + for(int i = 0; i completionItems = getCompletionsFor(contents, position); + completionItems = completionItems.stream().filter( + completionItem -> completionItem.getLabel().startsWith("Content Based Router") + ).collect(Collectors.toList()); + + assertThat(completionItems).hasSize(0); //Removing camel-k modeline insertion. Refactor later + } + + @Test + void testProvideInsertionOnEmptyJavaClass() throws Exception { + RouteTextBuilder.BlueprintContentWithPosition blueprint = + RouteTextBuilder.createJavaBlueprintClass(""); + + List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + completionItems = completionItems.stream().filter( + completionItem -> completionItem.getLabel().startsWith("Content Based Router") + ).collect(Collectors.toList()); + + + assertThat(completionItems).hasSize(0); + } + + @Test + void testProvideInsertionOnEmptyJavaCamelRoute() throws Exception { + RouteTextBuilder.BlueprintContentWithPosition blueprint = + RouteTextBuilder.createJavaBlueprintCamelRoute(""); + + List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + completionItems = completionItems.stream().filter( + completionItem -> completionItem.getLabel().startsWith("Content Based Router") + ).collect(Collectors.toList()); + + assertThat(completionItems).hasSize(0); + } + + @Test + void testProvideInsertionAfterFromOnCamelRoute() throws Exception { + RouteTextBuilder.BlueprintContentWithPosition blueprint = + RouteTextBuilder.createJavaBlueprintCamelRoute(FROM_ROUTE); + + List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + completionItems = completionItems.stream().filter( + completionItem -> completionItem.getLabel().startsWith("Content Based Router") + ).collect(Collectors.toList()); + + + assertThat(completionItems).hasSize(1); + } + + + private List getCompletionsFor(String contents, Position position) throws Exception { + CamelLanguageServer camelLanguageServer = initializeLanguageServer(contents, ".java"); + + CompletableFuture, CompletionList>> completions = getCompletionFor( + camelLanguageServer, position); + + return completions.get().getLeft(); + } +} diff --git a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java index 052c5edb..f65da16a 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java @@ -16,11 +16,23 @@ */ package com.github.cameltooling.lsp.internal.util; +import org.eclipse.lsp4j.Position; + public class RouteTextBuilder { public static final String XML_PREFIX_FROM = "\n"; private static final String XML_SUFFIX_FROM_BLUEPRINT = "\" xmlns=\"http://camel.apache.org/schema/blueprint\"/>\n"; + + private static final String JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_IMPORT + = "import org.apache.camel.builder.RouteBuilder;"; + + private static final String JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION = "public class TestRoute"; + + private static final String JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_EXTEMD = "extends RouteBuilder"; + + private static final String JAVA_CLASS_BLUEPRINT_CONFIGURE_METHOD_DECLARATION = "public void configure()"; + /** * @param camelUri @@ -38,4 +50,76 @@ public static String createXMLBlueprintRoute(String camelUri) { return XML_PREFIX_FROM + camelUri + XML_SUFFIX_FROM_BLUEPRINT; } + /** + * @param javaClassContent + * @return builds an empty Java class with the specified content and the cursor position inside and after + * contents + */ + public static BlueprintContentWithPosition createJavaBlueprintClass(String javaClassContent) { + String newLine = System.getProperty("line.separator"); + String[] contentSplit = javaClassContent.split(newLine); + int lineOffset = contentSplit.length; + int characterOffset = contentSplit[contentSplit.length-1].length(); + + if (javaClassContent.startsWith(newLine)) { + lineOffset += 1; + } + + if (javaClassContent.endsWith(newLine)) { + lineOffset +=1; + characterOffset = 0; + } + + return new BlueprintContentWithPosition( + JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION + newLine + + "{" + newLine + + javaClassContent + newLine + + "}" + newLine + , 2+lineOffset, characterOffset); + } + + /** + * @param camelRoute + * @return builds an empty Java class with the specified content and the cursor position placed inside configure + * method and after content. + */ + public static BlueprintContentWithPosition createJavaBlueprintCamelRoute(String camelRoute) { + String newLine = System.getProperty("line.separator"); + String[] contentSplit = camelRoute.split(newLine); + int lineOffset = contentSplit.length - 1; + int characterOffset = contentSplit[contentSplit.length-1].length(); + + if (camelRoute.startsWith(newLine)) { + lineOffset += 1; + } + + if (camelRoute.endsWith(newLine)) { + lineOffset +=1; + characterOffset = 0; + } + + return new BlueprintContentWithPosition( + JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_IMPORT + newLine + + JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION + newLine + + JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_EXTEMD + newLine + + "{" + newLine + + camelRoute + newLine + + "}" + newLine + , 4 + lineOffset,characterOffset); + } + + public static class BlueprintContentWithPosition { + public String content; + public Position position; + + public BlueprintContentWithPosition(String content, Position position) { + this.content = content; + this.position = position; + } + + public BlueprintContentWithPosition(String content, int line, int character) { + this.content = content; + this.position = new Position(line, character); + } + } } From d8f0ec993e06c904952c7c36564ee921c2347907 Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Mon, 9 Jan 2023 11:56:27 +0100 Subject: [PATCH 02/11] Saving changes --- .../github/cameltooling/lsp/internal/parser/CamelEIPParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java index 93af45e7..2f194b81 100644 --- a/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java +++ b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java @@ -17,7 +17,7 @@ public CamelEIPParser(TextDocumentItem textDocumentItem) { } public boolean canPutEIP(Position position) { - Pattern CHOICE_EIP_PATTERN = Pattern.compile("\\)\\s*.?c?h?o?i?c?e?\\(?$", Pattern.MULTILINE); + Pattern CHOICE_EIP_PATTERN = Pattern.compile("\\)\\s*.[c[h[o[i[c[e]?]?]?]?]?]?\\(?$", Pattern.MULTILINE); ParserFileHelperUtil util = new ParserFileHelperUtil(); String textUntilPosition = util.getTextUntilPosition(document, position); From 6d89bcc497d04c3a9d0522f0766a387a956846e5 Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Mon, 9 Jan 2023 11:58:03 +0100 Subject: [PATCH 03/11] Saving changes --- .../completion/eip/EIPChoiceCompletionTest.java | 17 +++++++++++++++++ .../lsp/internal/util/RouteTextBuilder.java | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java index 9e729fc6..ed2ba58d 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java @@ -21,6 +21,9 @@ public class EIPChoiceCompletionTest extends AbstractCamelLanguageServerTest { private static final Position BEGINNING_OF_FILE = new Position(0,0); private static final String FROM_ROUTE = "from(\"timer:foo?period={{timer.period}}\")"; + private static final String FROM_ROUTE_WITH_LINE_BREAKS_AND_TABS + = "from(\"timer:foo?period={{timer.period}}\")\n\t.bean()\n.d"; + @Test void testProvideInsertionOnEmptyJavaFile() throws Exception { @@ -76,6 +79,20 @@ void testProvideInsertionAfterFromOnCamelRoute() throws Exception { assertThat(completionItems).hasSize(1); } + @Test + void testProvideInsertionAfterFromOnCamelRouteWithLineBreaks() throws Exception { + RouteTextBuilder.BlueprintContentWithPosition blueprint = + RouteTextBuilder.createJavaBlueprintCamelRoute(FROM_ROUTE_WITH_LINE_BREAKS_AND_TABS); + + List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + completionItems = completionItems.stream().filter( + completionItem -> completionItem.getLabel().startsWith("Content Based Router") + ).collect(Collectors.toList()); + + + assertThat(completionItems).hasSize(1); + } + private List getCompletionsFor(String contents, Position position) throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer(contents, ".java"); diff --git a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java index f65da16a..40fd0155 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java @@ -100,7 +100,7 @@ public static BlueprintContentWithPosition createJavaBlueprintCamelRoute(String return new BlueprintContentWithPosition( JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_IMPORT + newLine + - JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION + newLine + + JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION + newLine + JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_EXTEMD + newLine + "{" + newLine + camelRoute + newLine + From 943bf57e91609e2af1ab67df1a8b04f667b2ef5b Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Mon, 9 Jan 2023 14:12:42 +0100 Subject: [PATCH 04/11] Fixed bug on choice EIP checking --- .../github/cameltooling/lsp/internal/parser/CamelEIPParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java index 2f194b81..bf8e4e42 100644 --- a/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java +++ b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java @@ -17,7 +17,7 @@ public CamelEIPParser(TextDocumentItem textDocumentItem) { } public boolean canPutEIP(Position position) { - Pattern CHOICE_EIP_PATTERN = Pattern.compile("\\)\\s*.[c[h[o[i[c[e]?]?]?]?]?]?\\(?$", Pattern.MULTILINE); + Pattern CHOICE_EIP_PATTERN = Pattern.compile("\\)\\s*[.[c[h[o[i[c[e]?]?]?]?]?]?]?\\(?$", Pattern.MULTILINE); ParserFileHelperUtil util = new ParserFileHelperUtil(); String textUntilPosition = util.getTextUntilPosition(document, position); From 98a3e97be26c902700c624116039f8a412f857ea Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Mon, 9 Jan 2023 14:20:50 +0100 Subject: [PATCH 05/11] Added another test for what seemed like a bug according to regexr but it works fine...? Leaving it as is because I would have to use capturing group which have a higher load to fix it --- .../eip/EIPChoiceCompletionTest.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java index ed2ba58d..0fd8d761 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java @@ -22,7 +22,10 @@ public class EIPChoiceCompletionTest extends AbstractCamelLanguageServerTest { private static final String FROM_ROUTE = "from(\"timer:foo?period={{timer.period}}\")"; private static final String FROM_ROUTE_WITH_LINE_BREAKS_AND_TABS - = "from(\"timer:foo?period={{timer.period}}\")\n\t.bean()\n.d"; + = "from(\"timer:foo?period={{timer.period}}\")\n\t.bean()\n"; + + private static final String FROM_ROUTE_WITH_CHOICE_EIP_MID_WRITTEN + = "from(\"timer:foo?period={{timer.period}}\")\n\t.ch\n"; @Test @@ -93,6 +96,20 @@ void testProvideInsertionAfterFromOnCamelRouteWithLineBreaks() throws Exception assertThat(completionItems).hasSize(1); } + @Test + void testProvideInsertionMidWritingChoice() throws Exception { + RouteTextBuilder.BlueprintContentWithPosition blueprint = + RouteTextBuilder.createJavaBlueprintCamelRoute(FROM_ROUTE_WITH_CHOICE_EIP_MID_WRITTEN); + + List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + completionItems = completionItems.stream().filter( + completionItem -> completionItem.getLabel().startsWith("Content Based Router") + ).collect(Collectors.toList()); + + + assertThat(completionItems).hasSize(1); + } + private List getCompletionsFor(String contents, Position position) throws Exception { CamelLanguageServer camelLanguageServer = initializeLanguageServer(contents, ".java"); From c07727423752fa0a07db5e7210cbfc1bf6c58a5a Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Mon, 9 Jan 2023 14:30:20 +0100 Subject: [PATCH 06/11] Refactoring RouteTextBuilder --- .../eip/EIPChoiceCompletionTest.java | 2 -- .../lsp/internal/util/RouteTextBuilder.java | 20 ++++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java index 0fd8d761..5e6af451 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java @@ -18,8 +18,6 @@ public class EIPChoiceCompletionTest extends AbstractCamelLanguageServerTest { - private static final Position BEGINNING_OF_FILE = new Position(0,0); - private static final String FROM_ROUTE = "from(\"timer:foo?period={{timer.period}}\")"; private static final String FROM_ROUTE_WITH_LINE_BREAKS_AND_TABS = "from(\"timer:foo?period={{timer.period}}\")\n\t.bean()\n"; diff --git a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java index 40fd0155..c190c169 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java @@ -24,14 +24,14 @@ public class RouteTextBuilder { private static final String XML_SUFFIX_FROM_SPRING = "\" xmlns=\"http://camel.apache.org/schema/spring\"/>\n"; private static final String XML_SUFFIX_FROM_BLUEPRINT = "\" xmlns=\"http://camel.apache.org/schema/blueprint\"/>\n"; - private static final String JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_IMPORT + private static final String CAMEL_ROUTEBUILDER_IMPORT = "import org.apache.camel.builder.RouteBuilder;"; - private static final String JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION = "public class TestRoute"; + private static final String CLASS_DECLARATION = "public class TestRoute"; - private static final String JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_EXTEMD = "extends RouteBuilder"; + private static final String CAMEL_ROUTEBUILDER_EXTEMD = "extends RouteBuilder"; - private static final String JAVA_CLASS_BLUEPRINT_CONFIGURE_METHOD_DECLARATION = "public void configure()"; + private static final String CONFIGURE_METHOD_DECLARATION = "public void configure()"; /** @@ -71,7 +71,7 @@ public static BlueprintContentWithPosition createJavaBlueprintClass(String javaC } return new BlueprintContentWithPosition( - JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION + newLine + + CLASS_DECLARATION + newLine + "{" + newLine + javaClassContent + newLine + "}" + newLine @@ -99,13 +99,15 @@ public static BlueprintContentWithPosition createJavaBlueprintCamelRoute(String } return new BlueprintContentWithPosition( - JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_IMPORT + newLine + - JAVA_CLASS_BLUEPRINT_CLASS_DECLARATION + newLine + - JAVA_CLASS_BLUEPRINT_CAMEL_ROUTEBUILDER_EXTEMD + newLine + + CAMEL_ROUTEBUILDER_IMPORT + newLine + + CLASS_DECLARATION + newLine + + CAMEL_ROUTEBUILDER_EXTEMD + newLine + "{" + newLine + + CONFIGURE_METHOD_DECLARATION + "{" + newLine + camelRoute + newLine + + "}" + newLine + "}" + newLine - , 4 + lineOffset,characterOffset); + , 5 + lineOffset,characterOffset); } public static class BlueprintContentWithPosition { From 2072ef7c6017213d8a41599096044d1b4ef41132 Mon Sep 17 00:00:00 2001 From: joshiraez Date: Tue, 10 Jan 2023 01:30:25 +0100 Subject: [PATCH 07/11] Fixed tests on Windows, removing System.lineSeparator as some tests were written to just have "\n" independently on the system so they broke. It didn't make sense to leave the carriage return as it would be treated as another whitespace character so I decided to simplify it --- .../lsp/internal/parser/ParserFileHelperUtil.java | 8 +++----- .../cameltooling/lsp/internal/util/RouteTextBuilder.java | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java b/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java index 4a249fd9..4b3be6da 100644 --- a/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java +++ b/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java @@ -19,6 +19,8 @@ import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.TextDocumentItem; +import java.util.regex.Pattern; + public class ParserFileHelperUtil { public String getLine(TextDocumentItem textDocumentItem, Position position) { @@ -38,14 +40,10 @@ public String getLine(String text, int line) { } public String getTextUntilPosition(TextDocumentItem document, Position position) { - String newLine = System.getProperty("line.separator"); + String newLine = "\n"; String[] lines = document.getText().split(newLine); String textUntilPosition = ""; - if(document.getText().startsWith(newLine)) { - textUntilPosition += newLine; - } - for(int i = 0; i Date: Tue, 10 Jan 2023 01:32:21 +0100 Subject: [PATCH 08/11] Refactored blueprint terminology to document --- .../eip/EIPChoiceCompletionTest.java | 30 +++++++++---------- .../lsp/internal/util/RouteTextBuilder.java | 14 ++++----- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java index 5e6af451..1592af0d 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/completion/eip/EIPChoiceCompletionTest.java @@ -41,10 +41,10 @@ void testProvideInsertionOnEmptyJavaFile() throws Exception { @Test void testProvideInsertionOnEmptyJavaClass() throws Exception { - RouteTextBuilder.BlueprintContentWithPosition blueprint = - RouteTextBuilder.createJavaBlueprintClass(""); + RouteTextBuilder.DocumentContentWithPosition document = + RouteTextBuilder.createJavaDocumentClass(""); - List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + List completionItems = getCompletionsFor(document.content, document.position); completionItems = completionItems.stream().filter( completionItem -> completionItem.getLabel().startsWith("Content Based Router") ).collect(Collectors.toList()); @@ -55,10 +55,10 @@ void testProvideInsertionOnEmptyJavaClass() throws Exception { @Test void testProvideInsertionOnEmptyJavaCamelRoute() throws Exception { - RouteTextBuilder.BlueprintContentWithPosition blueprint = - RouteTextBuilder.createJavaBlueprintCamelRoute(""); + RouteTextBuilder.DocumentContentWithPosition document = + RouteTextBuilder.createJavaDocumentCamelRoute(""); - List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + List completionItems = getCompletionsFor(document.content, document.position); completionItems = completionItems.stream().filter( completionItem -> completionItem.getLabel().startsWith("Content Based Router") ).collect(Collectors.toList()); @@ -68,10 +68,10 @@ void testProvideInsertionOnEmptyJavaCamelRoute() throws Exception { @Test void testProvideInsertionAfterFromOnCamelRoute() throws Exception { - RouteTextBuilder.BlueprintContentWithPosition blueprint = - RouteTextBuilder.createJavaBlueprintCamelRoute(FROM_ROUTE); + RouteTextBuilder.DocumentContentWithPosition document = + RouteTextBuilder.createJavaDocumentCamelRoute(FROM_ROUTE); - List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + List completionItems = getCompletionsFor(document.content, document.position); completionItems = completionItems.stream().filter( completionItem -> completionItem.getLabel().startsWith("Content Based Router") ).collect(Collectors.toList()); @@ -82,10 +82,10 @@ void testProvideInsertionAfterFromOnCamelRoute() throws Exception { @Test void testProvideInsertionAfterFromOnCamelRouteWithLineBreaks() throws Exception { - RouteTextBuilder.BlueprintContentWithPosition blueprint = - RouteTextBuilder.createJavaBlueprintCamelRoute(FROM_ROUTE_WITH_LINE_BREAKS_AND_TABS); + RouteTextBuilder.DocumentContentWithPosition document = + RouteTextBuilder.createJavaDocumentCamelRoute(FROM_ROUTE_WITH_LINE_BREAKS_AND_TABS); - List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + List completionItems = getCompletionsFor(document.content, document.position); completionItems = completionItems.stream().filter( completionItem -> completionItem.getLabel().startsWith("Content Based Router") ).collect(Collectors.toList()); @@ -96,10 +96,10 @@ void testProvideInsertionAfterFromOnCamelRouteWithLineBreaks() throws Exception @Test void testProvideInsertionMidWritingChoice() throws Exception { - RouteTextBuilder.BlueprintContentWithPosition blueprint = - RouteTextBuilder.createJavaBlueprintCamelRoute(FROM_ROUTE_WITH_CHOICE_EIP_MID_WRITTEN); + RouteTextBuilder.DocumentContentWithPosition document = + RouteTextBuilder.createJavaDocumentCamelRoute(FROM_ROUTE_WITH_CHOICE_EIP_MID_WRITTEN); - List completionItems = getCompletionsFor(blueprint.content, blueprint.position); + List completionItems = getCompletionsFor(document.content, document.position); completionItems = completionItems.stream().filter( completionItem -> completionItem.getLabel().startsWith("Content Based Router") ).collect(Collectors.toList()); diff --git a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java index 74c9e6bf..99c7c4a4 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java @@ -55,7 +55,7 @@ public static String createXMLBlueprintRoute(String camelUri) { * @return builds an empty Java class with the specified content and the cursor position inside and after * contents */ - public static BlueprintContentWithPosition createJavaBlueprintClass(String javaClassContent) { + public static DocumentContentWithPosition createJavaDocumentClass(String javaClassContent) { String newLine = System.getProperty("line.separator"); String[] contentSplit = javaClassContent.split(newLine); int lineOffset = contentSplit.length; @@ -70,7 +70,7 @@ public static BlueprintContentWithPosition createJavaBlueprintClass(String javaC characterOffset = 0; } - return new BlueprintContentWithPosition( + return new DocumentContentWithPosition( CLASS_DECLARATION + newLine + "{" + newLine + javaClassContent + newLine @@ -83,7 +83,7 @@ public static BlueprintContentWithPosition createJavaBlueprintClass(String javaC * @return builds an empty Java class with the specified content and the cursor position placed inside configure * method and after content. */ - public static BlueprintContentWithPosition createJavaBlueprintCamelRoute(String camelRoute) { + public static DocumentContentWithPosition createJavaDocumentCamelRoute(String camelRoute) { String newLine = "\n"; String[] contentSplit = camelRoute.split(newLine); int lineOffset = contentSplit.length - 1; @@ -98,7 +98,7 @@ public static BlueprintContentWithPosition createJavaBlueprintCamelRoute(String characterOffset = 0; } - return new BlueprintContentWithPosition( + return new DocumentContentWithPosition( CAMEL_ROUTEBUILDER_IMPORT + newLine + CLASS_DECLARATION + newLine + CAMEL_ROUTEBUILDER_EXTEMD + newLine + @@ -110,16 +110,16 @@ public static BlueprintContentWithPosition createJavaBlueprintCamelRoute(String , 5 + lineOffset,characterOffset); } - public static class BlueprintContentWithPosition { + public static class DocumentContentWithPosition { public String content; public Position position; - public BlueprintContentWithPosition(String content, Position position) { + public DocumentContentWithPosition(String content, Position position) { this.content = content; this.position = position; } - public BlueprintContentWithPosition(String content, int line, int character) { + public DocumentContentWithPosition(String content, int line, int character) { this.content = content; this.position = new Position(line, character); } From e512c5edb08c20814328946f5f21262229a1aa18 Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Fri, 13 Jan 2023 13:01:49 +0100 Subject: [PATCH 09/11] Line separator os specific in document builder --- .../github/cameltooling/lsp/internal/util/RouteTextBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java index 99c7c4a4..859ca4d1 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java @@ -84,7 +84,7 @@ public static DocumentContentWithPosition createJavaDocumentClass(String javaCla * method and after content. */ public static DocumentContentWithPosition createJavaDocumentCamelRoute(String camelRoute) { - String newLine = "\n"; + String newLine = System.getProperty("line.separator"); String[] contentSplit = camelRoute.split(newLine); int lineOffset = contentSplit.length - 1; int characterOffset = contentSplit[contentSplit.length-1].length(); From 1c72b3d69912318cdccd5de778a8919ce74cb70a Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Fri, 13 Jan 2023 13:32:12 +0100 Subject: [PATCH 10/11] Forgot that this was what proced the bug :)))) --- .../cameltooling/lsp/internal/util/RouteTextBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java index 859ca4d1..11c037b6 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java @@ -56,7 +56,7 @@ public static String createXMLBlueprintRoute(String camelUri) { * contents */ public static DocumentContentWithPosition createJavaDocumentClass(String javaClassContent) { - String newLine = System.getProperty("line.separator"); + String newLine = "\n"; String[] contentSplit = javaClassContent.split(newLine); int lineOffset = contentSplit.length; int characterOffset = contentSplit[contentSplit.length-1].length(); @@ -84,7 +84,7 @@ public static DocumentContentWithPosition createJavaDocumentClass(String javaCla * method and after content. */ public static DocumentContentWithPosition createJavaDocumentCamelRoute(String camelRoute) { - String newLine = System.getProperty("line.separator"); + String newLine = "\n"; String[] contentSplit = camelRoute.split(newLine); int lineOffset = contentSplit.length - 1; int characterOffset = contentSplit[contentSplit.length-1].length(); From 45127a272e7bc8601558a5292e88a655aa9066e3 Mon Sep 17 00:00:00 2001 From: JoshiRaez Date: Fri, 20 Jan 2023 16:11:23 +0100 Subject: [PATCH 11/11] Refactoring with Aurelien suggestions --- .../lsp/internal/parser/CamelEIPParser.java | 9 ++-- .../internal/parser/ParserFileHelperUtil.java | 8 +-- .../eip/EIPChoiceCompletionTest.java | 52 +++++++++---------- .../lsp/internal/util/RouteTextBuilder.java | 13 +++-- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java index bf8e4e42..dc67774a 100644 --- a/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java +++ b/src/main/java/com/github/cameltooling/lsp/internal/parser/CamelEIPParser.java @@ -10,6 +10,7 @@ public class CamelEIPParser { + private static final String LATEST_LTS_URL = "https://camel.apache.org/components/3.20.x"; private final TextDocumentItem document; public CamelEIPParser(TextDocumentItem textDocumentItem) { @@ -17,11 +18,11 @@ public CamelEIPParser(TextDocumentItem textDocumentItem) { } public boolean canPutEIP(Position position) { - Pattern CHOICE_EIP_PATTERN = Pattern.compile("\\)\\s*[.[c[h[o[i[c[e]?]?]?]?]?]?]?\\(?$", Pattern.MULTILINE); + Pattern choiceEipPattern = Pattern.compile("\\)\\s*[.[c[h[o[i[c[e]?]?]?]?]?]?]?\\(?$", Pattern.MULTILINE); ParserFileHelperUtil util = new ParserFileHelperUtil(); String textUntilPosition = util.getTextUntilPosition(document, position); - return CHOICE_EIP_PATTERN.matcher(textUntilPosition).find(); + return choiceEipPattern.matcher(textUntilPosition).find(); } public CompletableFuture> getCompletions() { @@ -31,10 +32,10 @@ public CompletableFuture> getCompletions() { } private CompletionItem choiceEIPcompletion() { - String newLine = System.getProperty("line.separator"); + String newLine = "\n"; CompletionItem completion = new CompletionItem("Content Based Router"); completion.setDocumentation( - "Read more: https://camel.apache.org/components/3.11.x/eips/content-based-router-eip.html" + "Read more: "+LATEST_LTS_URL+"/eips/choice-eip.html" ); completion.setInsertText( ".choice()" + newLine + diff --git a/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java b/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java index 4b3be6da..7fe1a128 100644 --- a/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java +++ b/src/main/java/com/github/cameltooling/lsp/internal/parser/ParserFileHelperUtil.java @@ -42,18 +42,18 @@ public String getLine(String text, int line) { public String getTextUntilPosition(TextDocumentItem document, Position position) { String newLine = "\n"; String[] lines = document.getText().split(newLine); - String textUntilPosition = ""; + StringBuilder textUntilPosition = new StringBuilder(""); for(int i = 0; i completionItems = getCompletionsFor(contents, position); - completionItems = completionItems.stream().filter( - completionItem -> completionItem.getLabel().startsWith("Content Based Router") - ).collect(Collectors.toList()); + completionItems = getContentBasedRouterCompletionItems(completionItems); - assertThat(completionItems).hasSize(0); //Removing camel-k modeline insertion. Refactor later + assertThat(completionItems).isEmpty(); } @Test @@ -44,13 +44,11 @@ void testProvideInsertionOnEmptyJavaClass() throws Exception { RouteTextBuilder.DocumentContentWithPosition document = RouteTextBuilder.createJavaDocumentClass(""); - List completionItems = getCompletionsFor(document.content, document.position); - completionItems = completionItems.stream().filter( - completionItem -> completionItem.getLabel().startsWith("Content Based Router") - ).collect(Collectors.toList()); + List completionItems = getCompletionsFor(document.getContent(), document.getPosition()); + completionItems = getContentBasedRouterCompletionItems(completionItems); - assertThat(completionItems).hasSize(0); + assertThat(completionItems).isEmpty(); } @Test @@ -58,10 +56,8 @@ void testProvideInsertionOnEmptyJavaCamelRoute() throws Exception { RouteTextBuilder.DocumentContentWithPosition document = RouteTextBuilder.createJavaDocumentCamelRoute(""); - List completionItems = getCompletionsFor(document.content, document.position); - completionItems = completionItems.stream().filter( - completionItem -> completionItem.getLabel().startsWith("Content Based Router") - ).collect(Collectors.toList()); + List completionItems = getCompletionsFor(document.getContent(), document.getPosition()); + completionItems = getContentBasedRouterCompletionItems(completionItems); assertThat(completionItems).hasSize(0); } @@ -71,10 +67,8 @@ void testProvideInsertionAfterFromOnCamelRoute() throws Exception { RouteTextBuilder.DocumentContentWithPosition document = RouteTextBuilder.createJavaDocumentCamelRoute(FROM_ROUTE); - List completionItems = getCompletionsFor(document.content, document.position); - completionItems = completionItems.stream().filter( - completionItem -> completionItem.getLabel().startsWith("Content Based Router") - ).collect(Collectors.toList()); + List completionItems = getCompletionsFor(document.getContent(), document.getPosition()); + completionItems = getContentBasedRouterCompletionItems(completionItems); assertThat(completionItems).hasSize(1); @@ -85,10 +79,8 @@ void testProvideInsertionAfterFromOnCamelRouteWithLineBreaks() throws Exception RouteTextBuilder.DocumentContentWithPosition document = RouteTextBuilder.createJavaDocumentCamelRoute(FROM_ROUTE_WITH_LINE_BREAKS_AND_TABS); - List completionItems = getCompletionsFor(document.content, document.position); - completionItems = completionItems.stream().filter( - completionItem -> completionItem.getLabel().startsWith("Content Based Router") - ).collect(Collectors.toList()); + List completionItems = getCompletionsFor(document.getContent(), document.getPosition()); + completionItems = getContentBasedRouterCompletionItems(completionItems); assertThat(completionItems).hasSize(1); @@ -99,10 +91,8 @@ void testProvideInsertionMidWritingChoice() throws Exception { RouteTextBuilder.DocumentContentWithPosition document = RouteTextBuilder.createJavaDocumentCamelRoute(FROM_ROUTE_WITH_CHOICE_EIP_MID_WRITTEN); - List completionItems = getCompletionsFor(document.content, document.position); - completionItems = completionItems.stream().filter( - completionItem -> completionItem.getLabel().startsWith("Content Based Router") - ).collect(Collectors.toList()); + List completionItems = getCompletionsFor(document.getContent(), document.getPosition()); + completionItems = getContentBasedRouterCompletionItems(completionItems); assertThat(completionItems).hasSize(1); @@ -117,4 +107,12 @@ private List getCompletionsFor(String contents, Position positio return completions.get().getLeft(); } + + @NotNull + private List getContentBasedRouterCompletionItems(List completionItems) { + + return completionItems.stream().filter( + completionItem -> completionItem.getLabel().startsWith(CONTENT_BASED_ROUTER_LABEL) + ).collect(Collectors.toList()); + } } diff --git a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java index 11c037b6..8e899832 100644 --- a/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java +++ b/src/test/java/com/github/cameltooling/lsp/internal/util/RouteTextBuilder.java @@ -114,14 +114,17 @@ public static class DocumentContentWithPosition { public String content; public Position position; - public DocumentContentWithPosition(String content, Position position) { - this.content = content; - this.position = position; - } - public DocumentContentWithPosition(String content, int line, int character) { this.content = content; this.position = new Position(line, character); } + + public String getContent() { + return content; + } + + public Position getPosition() { + return position; + } } }