From 8827ec748f075bf45e21c681bf350dcdcdd2dd57 Mon Sep 17 00:00:00 2001 From: maria77102 <121297022+maria77102@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:12:58 +0100 Subject: [PATCH] Automating Formatting of Rune Code (#859) * Created formatter interface * Implement interface + first Test * Fix formatting test + implementation * Enhanced test suite * Implement suggested changes * Improved interface methods/exception handling and added logging * Added formatting tool method * Add dependencies for logging in tools project * Improve implementation of command line tool * Formatting java code * Made formatting happen in-memory * Update logs when resource saved * Fixed logger class name --- .../rosetta/RosettaRuntimeModule.xtend | 6 ++ .../formatting2/ResourceFormatterService.java | 70 ++++++++++++++++ .../formatting2/XtextResourceFormatter.java | 76 ++++++++++++++++++ .../ResourceFormatterServiceTest.java | 75 +++++++++++++++++ .../expected/typeAlias.rosetta | 3 + .../typeAliasWithDocumentation.rosetta | 7 ++ .../formatting-test/input/typeAlias.rosetta | 7 ++ .../input/typeAliasWithDocumentation.rosetta | 8 ++ rosetta-tools/pom.xml | 8 ++ .../rosetta/tools/ResourceFormattingTool.java | 80 +++++++++++++++++++ 10 files changed, 340 insertions(+) create mode 100644 rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/ResourceFormatterService.java create mode 100644 rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/XtextResourceFormatter.java create mode 100644 rosetta-testing/src/test/java/com/regnosys/rosetta/formatting2/ResourceFormatterServiceTest.java create mode 100644 rosetta-testing/src/test/resources/formatting-test/expected/typeAlias.rosetta create mode 100644 rosetta-testing/src/test/resources/formatting-test/expected/typeAliasWithDocumentation.rosetta create mode 100644 rosetta-testing/src/test/resources/formatting-test/input/typeAlias.rosetta create mode 100644 rosetta-testing/src/test/resources/formatting-test/input/typeAliasWithDocumentation.rosetta create mode 100644 rosetta-tools/src/main/java/com/regnosys/rosetta/tools/ResourceFormattingTool.java diff --git a/rosetta-lang/src/main/java/com/regnosys/rosetta/RosettaRuntimeModule.xtend b/rosetta-lang/src/main/java/com/regnosys/rosetta/RosettaRuntimeModule.xtend index d2dbce4d9..a6de2036a 100644 --- a/rosetta-lang/src/main/java/com/regnosys/rosetta/RosettaRuntimeModule.xtend +++ b/rosetta-lang/src/main/java/com/regnosys/rosetta/RosettaRuntimeModule.xtend @@ -47,6 +47,8 @@ import com.regnosys.rosetta.config.RosettaConfiguration import com.regnosys.rosetta.config.file.FileBasedRosettaConfigurationProvider import com.regnosys.rosetta.cache.IRequestScopedCache import com.regnosys.rosetta.cache.RequestScopedCache +import com.regnosys.rosetta.formatting2.XtextResourceFormatter +import com.regnosys.rosetta.formatting2.ResourceFormatterService /* Use this class to register components to be used at runtime / without the Equinox extension registry.*/ class RosettaRuntimeModule extends AbstractRosettaRuntimeModule { @@ -148,4 +150,8 @@ class RosettaRuntimeModule extends AbstractRosettaRuntimeModule { def Class extends IRequestScopedCache> bindIRequestScopedCache() { RequestScopedCache } + + def Class extends ResourceFormatterService> bindResourceFormatterService() { + XtextResourceFormatter + } } diff --git a/rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/ResourceFormatterService.java b/rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/ResourceFormatterService.java new file mode 100644 index 000000000..fd6633330 --- /dev/null +++ b/rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/ResourceFormatterService.java @@ -0,0 +1,70 @@ +package com.regnosys.rosetta.formatting2; + +import java.util.Collection; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.xtext.preferences.ITypedPreferenceValues; +import org.eclipse.xtext.resource.XtextResource; + +public interface ResourceFormatterService { + + /** + * Formats each {@link XtextResource} in the provided collection in-memory. + *
+ * This method iterates over the given collection of resources and applies formatting + * directly to each resource. Formatting may include indentation, spacing adjustments, + * and other stylistic improvements to ensure consistency and readability of the resources. + *
+ * + * @param resources a collection of {@link XtextResource} objects to be formatted + */ + default void formatCollection(Collection+ * This method applies formatting directly to the specified resource. Formatting can include + * adjustments to indentation, spacing, and other stylistic elements to ensure consistency + * and readability of the resource content. + *
+ * + * @param resources the {@link XtextResource} to format + * @param preferenceValues an {@link ITypedPreferenceValues} object containing formatting preferences, + * or {@code null} if no preferences are specified + */ + default void formatXtextResource(XtextResource resource) { + formatXtextResource(resource, null); + } + + /** + * Formats each {@link XtextResource} in the provided collection in-memory, with specified formatting preferences. + *+ * This method iterates over the given collection of resources and applies formatting + * directly to each resource. Formatting may include indentation, spacing adjustments, + * and other stylistic improvements to ensure consistency and readability of the resources. + * The formatting can be customized based on the specified {@link ITypedPreferenceValues}. + * If no preferences are required, {@code preferenceValues} can be set to {@code null}. + *
+ * + * @param resources a collection of {@link XtextResource} objects to be formatted + * @param preferenceValues an {@link ITypedPreferenceValues} object containing formatting preferences, + * or {@code null} if no preferences are specified + */ + void formatCollection(Collection+ * This method applies formatting directly to the specified resource. Formatting can include + * adjustments to indentation, spacing, and other stylistic elements to ensure consistency + * and readability of the resource content. + * The formatting can be customized based on the specified {@link ITypedPreferenceValues}. + * If no preferences are required, {@code preferenceValues} can be set to {@code null}. + *
+ * + * @param resource the {@link XtextResource} to format + */ + void formatXtextResource(XtextResource resource, ITypedPreferenceValues preferenceValues); +} diff --git a/rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/XtextResourceFormatter.java b/rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/XtextResourceFormatter.java new file mode 100644 index 000000000..1027d86a6 --- /dev/null +++ b/rosetta-lang/src/main/java/com/regnosys/rosetta/formatting2/XtextResourceFormatter.java @@ -0,0 +1,76 @@ +package com.regnosys.rosetta.formatting2; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.List; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.xtext.formatting2.FormatterRequest; +import org.eclipse.xtext.formatting2.IFormatter2; +import org.eclipse.xtext.formatting2.regionaccess.ITextRegionAccess; +import org.eclipse.xtext.formatting2.regionaccess.ITextRegionRewriter; +import org.eclipse.xtext.formatting2.regionaccess.ITextReplacement; +import org.eclipse.xtext.formatting2.regionaccess.TextRegionAccessBuilder; +import org.eclipse.xtext.preferences.ITypedPreferenceValues; +import org.eclipse.xtext.resource.XtextResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Provider; + +public class XtextResourceFormatter implements ResourceFormatterService { + private static Logger LOGGER = LoggerFactory.getLogger(XtextResourceFormatter.class); + @Inject + private Provider+ * This tool uses the {@link ResourceFormatterService} to apply consistent formatting to each + * `.rosetta` file in the provided directory. It loads each file as a resource, applies + * formatting in-place, and saves the modified file back to disk. The tool can be run with a + * single directory path argument, which is used to locate `.rosetta` files. + *
+ * + *+ * java ResourceFormattingTool /path/to/directory + *+ *
+ * If no valid directory path is provided as an argument, the program will exit with an error message. + *
+ */ +public class ResourceFormattingTool { + private static Logger LOGGER = LoggerFactory.getLogger(ResourceFormattingTool.class); + + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("Please provide the directory path as an argument."); + System.exit(1); + } + + Path directory = Paths.get(args[0]); + if (!Files.isDirectory(directory)) { + System.out.println("The provided path is not a valid directory."); + System.exit(1); + } + + Injector inj = new RosettaStandaloneSetup().createInjectorAndDoEMFRegistration(); + ResourceSet resourceSet = inj.getInstance(ResourceSet.class); + ResourceFormatterService formatterService = inj.getInstance(ResourceFormatterService.class); + + try { + // Find all .rosetta files in the directory and load them from disk + List