Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.avaloq.tools.ddk.check.core.test/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Bundle-Vendor: Avaloq Group AG
Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-ActivationPolicy: lazy
Require-Bundle: com.avaloq.tools.ddk.check.core,
com.avaloq.tools.ddk.xtext,
com.avaloq.tools.ddk.xtext.test.core,
com.avaloq.tools.ddk.check.ui,
org.eclipse.xtext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

package com.avaloq.tools.ddk.check.core.test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
Expand Down Expand Up @@ -90,12 +91,18 @@ public List<JavaSource> generateAndCompile(final InputStream sourceStream) {
}
}
assertNotNull(type, "Should have an inferred Jvm model");
// Run the generator using an in-memory file system access
// Run the generator using an in-memory file system access; member injection wires the
// IFilePostProcessor so the LF ILineSeparatorInformation binding is actually exercised
InMemoryFileSystemAccess fsa = new InMemoryFileSystemAccess();
getInjector().injectMembers(fsa);
for (OutputConfiguration output : outputConfigurationProvider.getOutputConfigurations()) {
fsa.getOutputConfigurations().put(output.getName(), output);
}
generator.doGenerate(res, fsa);
// Generated content must be line-ending-deterministic (LF) on every platform.
for (java.util.Map.Entry<String, CharSequence> file : fsa.getTextFiles().entrySet()) {
assertEquals(-1, file.getValue().toString().indexOf('\r'), "generated file must not contain CR: " + file.getKey());
}
// We now should have a number of files.
String baseName = root.getPackageName() + '.' + root.getName();
String basePath = baseName.replace('.', '/');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2026 Avaloq Group AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Avaloq Group AG - initial API and implementation
*******************************************************************************/
package com.avaloq.tools.ddk.check.core.test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;

import org.eclipse.xtext.formatting.ILineSeparatorInformation;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import com.avaloq.tools.ddk.check.CheckInjectorProvider;
import com.avaloq.tools.ddk.xtext.formatting.LfLineSeparatorInformation;
import com.google.inject.Inject;


/**
* Guarantees the Check runtime injector resolves {@link ILineSeparatorInformation} to the LF
* binding, so headless generation is line-ending-deterministic. The other DDK language
* runtime modules declare the identical binding method; this test pins the Guice
* module-convention wiring they all rely on.
*/
@InjectWith(CheckInjectorProvider.class)
@ExtendWith(InjectionExtension.class)
@SuppressWarnings("nls")
public class CheckLineSeparatorBindingTest {

@Inject
private ILineSeparatorInformation lineSeparatorInformation;

@Test
public void runtimeInjectorBindsLfLineSeparator() {
assertInstanceOf(LfLineSeparatorInformation.class, lineSeparatorInformation, "Check runtime injector must bind the LF separator information");
assertEquals("\n", lineSeparatorInformation.getLineSeparator(), "bound separator must be LF");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.avaloq.tools.ddk.check.core.test.BugAig1314;
import com.avaloq.tools.ddk.check.core.test.BugAig830;
import com.avaloq.tools.ddk.check.core.test.BugDsl27;
import com.avaloq.tools.ddk.check.core.test.CheckLineSeparatorBindingTest;
import com.avaloq.tools.ddk.check.core.test.CheckScopingTest;
import com.avaloq.tools.ddk.check.core.test.IssueCodeToLabelMapGenerationTest;
import com.avaloq.tools.ddk.check.core.test.ProjectBasedTests;
Expand All @@ -35,6 +36,7 @@
// @Format-Off
IssueCodeValueTest.class,
BasicModelTest.class,
CheckLineSeparatorBindingTest.class,
BugAig830.class,
CheckScopingTest.class,
CheckValidationTest.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package com.avaloq.tools.ddk.check;

import org.eclipse.xtext.documentation.IEObjectDocumentationProvider;
import org.eclipse.xtext.formatting.ILineSeparatorInformation;
import org.eclipse.xtext.generator.IOutputConfigurationProvider;
import org.eclipse.xtext.linking.ILinkingService;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
Expand Down Expand Up @@ -40,6 +41,7 @@
import com.avaloq.tools.ddk.check.scoping.ExtensionPointAwareScopeProvider;
import com.avaloq.tools.ddk.check.typing.CheckExpressionHelper;
import com.avaloq.tools.ddk.check.typing.CheckTypeComputer;
import com.avaloq.tools.ddk.xtext.formatting.LfLineSeparatorInformation;
import com.google.inject.name.Names;


Expand All @@ -48,6 +50,17 @@
*/
@SuppressWarnings({"PMD.CouplingBetweenObjects", "restriction"})
public class CheckRuntimeModule extends com.avaloq.tools.ddk.check.AbstractCheckRuntimeModule {

/**
* Binds the generated-file line separator to LF so code generation is deterministic
* across platforms; headless builds otherwise fall back to the platform separator.
*
* @return the LF {@link ILineSeparatorInformation} implementation, never {@code null}
*/
public Class<? extends ILineSeparatorInformation> bindILineSeparatorInformation() {
return LfLineSeparatorInformation.class;
}

@Override
public Class<? extends XtextResource> bindXtextResource() {
return CheckBatchLinkableResource.class;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.google.inject.Inject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.AbstractFileSystemAccess
import org.eclipse.xtext.generator.IFileSystemAccess
import org.eclipse.xtext.generator.IFileSystemAccess2
import org.eclipse.xtext.xbase.compiler.JvmModelGenerator

import static org.eclipse.xtext.xbase.lib.IteratorExtensions.*
Expand All @@ -37,24 +36,23 @@ class CheckGenerator extends JvmModelGenerator {
@Inject ICheckGeneratorConfigProvider generatorConfigProvider;

override void doGenerate(Resource resource, IFileSystemAccess fsa) {
val lfFsa = new LfNormalizingFileSystemAccess(fsa as IFileSystemAccess2)
super.doGenerate(resource, lfFsa); // Generate validator, catalog, and preference initializer from inferred Jvm models.
super.doGenerate(resource, fsa); // Generate validator, catalog, and preference initializer from inferred Jvm models.
val config = generatorConfigProvider.get(resource?.URI);
for (catalog : toIterable(resource.allContents).filter(typeof(CheckCatalog))) {

lfFsa.generateFile(catalog.issueCodesFilePath, catalog.compileIssueCodes)
lfFsa.generateFile(catalog.standaloneSetupPath, catalog.compileStandaloneSetup)
fsa.generateFile(catalog.issueCodesFilePath, catalog.compileIssueCodes)
fsa.generateFile(catalog.standaloneSetupPath, catalog.compileStandaloneSetup)

// change output path for service registry
lfFsa.generateFile(
fsa.generateFile(
CheckUtil::serviceRegistryClassName,
CheckGeneratorConstants::CHECK_REGISTRY_OUTPUT,
catalog.generateServiceRegistry(CheckUtil::serviceRegistryClassName, fsa)
)
// generate documentation for SCA-checks only
if(config !== null && (config.doGenerateDocumentationForAllChecks || !config.generateLanguageInternalChecks)){
// change output path for html files to docs/
lfFsa.generateFile(catalog.docFileName, CheckGeneratorConstants::CHECK_DOC_OUTPUT, catalog.compileDoc)
fsa.generateFile(catalog.docFileName, CheckGeneratorConstants::CHECK_DOC_OUTPUT, catalog.compileDoc)
}
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Workflow {
}
code = {
encoding = "UTF-8"
lineDelimiter = "\r\n"
lineDelimiter = "\n"
fileHeader = "/*\n * generated by Xtext\n */"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package com.avaloq.tools.ddk.checkcfg;

import org.eclipse.xtext.conversion.IValueConverterService;
import org.eclipse.xtext.formatting.ILineSeparatorInformation;
import org.eclipse.xtext.generator.IGenerator;
import org.eclipse.xtext.naming.IQualifiedNameProvider;
import org.eclipse.xtext.resource.ILocationInFileProvider;
Expand All @@ -26,6 +27,7 @@
import com.avaloq.tools.ddk.checkcfg.resource.CheckCfgLocationInFileProvider;
import com.avaloq.tools.ddk.checkcfg.scoping.CheckCfgBatchLinkingService;
import com.avaloq.tools.ddk.checkcfg.scoping.CheckCfgScopeProvider;
import com.avaloq.tools.ddk.xtext.formatting.LfLineSeparatorInformation;
import com.google.inject.name.Names;


Expand All @@ -34,6 +36,16 @@
*/
public class CheckCfgRuntimeModule extends com.avaloq.tools.ddk.checkcfg.AbstractCheckCfgRuntimeModule {

/**
* Binds the generated-file line separator to LF so code generation is deterministic
* across platforms; headless builds otherwise fall back to the platform separator.
*
* @return the LF {@link ILineSeparatorInformation} implementation, never {@code null}
*/
public Class<? extends ILineSeparatorInformation> bindILineSeparatorInformation() {
return LfLineSeparatorInformation.class;
}

/**
* Custom location in file provider used for revealing and highlighting a model element in the editor.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.generator.AbstractFileSystemAccess;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.generator.IFileSystemAccess2;
import org.eclipse.xtext.generator.IGenerator;
import org.eclipse.xtext.xbase.lib.IteratorExtensions;

import com.avaloq.tools.ddk.check.generator.LfNormalizingFileSystemAccess;
import com.avaloq.tools.ddk.check.runtime.configuration.ICheckConfigurationStoreService;
import com.avaloq.tools.ddk.checkcfg.checkcfg.CheckConfiguration;
import com.google.common.collect.Iterables;
Expand Down Expand Up @@ -56,9 +54,8 @@ public void doGenerate(final Resource resource, final IFileSystemAccess fsa) {
if (fsa instanceof AbstractFileSystemAccess abstractFsa) {
abstractFsa.setOutputPath(outputPath());
}
final LfNormalizingFileSystemAccess lfFsa = new LfNormalizingFileSystemAccess((IFileSystemAccess2) fsa);
for (final CheckConfiguration configuration : Iterables.filter(IteratorExtensions.toIterable(resource.getAllContents()), CheckConfiguration.class)) {
lfFsa.generateFile(fileName(configuration), compile(configuration));
fsa.generateFile(fileName(configuration), compile(configuration));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Workflow {
}
code = {
encoding = "UTF-8"
lineDelimiter = "\r\n"
lineDelimiter = "\n"
fileHeader = "/*\n * generated by Xtext\n */"
preferXtendStubs = false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Workflow {
component = com.avaloq.tools.ddk.xtext.generator.util.CustomClassAwareEcoreGenerator {
genModel = "platform:/resource/${projectName}/model/ModelInference.genmodel"
generateEdit = false
lineDelimiter = "\n"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ Workflow {
component = EcoreGenerator auto-inject {
genModel = "platform:/resource/${projectName}/model/TypeModel.genmodel"
generateEdit=true
lineDelimiter = "\n"
}

component = EcoreGenerator auto-inject {
genModel = "platform:/resource/${projectName}/model/BuiltInTypeModel.genmodel"
generateEdit=false
lineDelimiter = "\n"
}
}
Loading