Skip to content
Snippets Groups Projects
Commit 69479d66 authored by René Schöne's avatar René Schöne
Browse files

Merge branch 'dev' into 'master'

0.4.0

Closes #27

See merge request !20
parents 2dffc2f1 699ebb7a
No related branches found
No related tags found
2 merge requests!200.4.0,!17WIP: Feature/better placeholders
Pipeline #12984 passed
Showing
with 549 additions and 658 deletions
...@@ -13,4 +13,3 @@ src/test/jastadd/*/*.ast ...@@ -13,4 +13,3 @@ src/test/jastadd/*/*.ast
src/test/jastadd/*/*.jadd src/test/jastadd/*/*.jadd
src/test/jastadd/*/*ResolverStubs.jrag src/test/jastadd/*/*ResolverStubs.jrag
!src/test/jastadd/*/MyRefResolver.jadd !src/test/jastadd/*/MyRefResolver.jadd
/gradle.properties
stages: stages:
- build - build
- test - test
- jar
- deploy - deploy
before_script:
- export GRADLE_USER_HOME=`pwd`/.gradle
cache:
paths:
- .gradle/wrapper
- .gradle/caches
build: build:
image: openjdk:8 image: openjdk:8
stage: build stage: build
script: script:
- ./gradlew --console=plain --build-cache assemble - ./gradlew --console=plain --no-daemon assemble fatJar
cache: artifacts:
key: "$CI_COMMIT_REF_NAME"
policy: push
paths: paths:
- build - "/builds/jastadd/relational-rags/build/libs/relast-*.jar"
- .gradle
test: test:
image: openjdk:8 image: openjdk:8
stage: test stage: test
script: script:
- ./gradlew --continue --console=plain --info check - ./gradlew --console=plain --no-daemon --info test
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- build
- .gradle
jar:
image: openjdk:8
stage: jar
script:
- ./gradlew --continue --console=plain --info jar
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- build
- .gradle
artifacts:
paths:
- "/builds/jastadd/*/build/libs/*relast*.jar"
pages: pages:
image: python:3.7-alpine image: python:3.7-alpine
...@@ -54,3 +37,27 @@ pages: ...@@ -54,3 +37,27 @@ pages:
- public - public
only: only:
- master - master
- main
publish:
image: openjdk:8
stage: deploy
needs:
- test
script:
- "./gradlew publish"
only:
- master
- main
publish_dev:
image: openjdk:8
stage: deploy
needs:
- test
script:
- "./gradlew setDevVersionForCI"
- "./gradlew publish"
except:
- master
- main
...@@ -23,33 +23,27 @@ This location can be [configured](#build-configuration). ...@@ -23,33 +23,27 @@ This location can be [configured](#build-configuration).
## Build configuration ## Build configuration
Currently, the test setup is configured within `build.gradle` using a specialized Gradle task `RelastTest`. Currently, the test setup is configured within `build.gradle` using a specialized Gradle task `RelastTest` provided by the [preprocessor testing Gradle plugin][preprocessor-testing].
An example configuration might look like: An example configuration might look like:
```groovy ```groovy
task compileMultipleTest(type: RelastTest) { task compileMultipleTest(type: RelastTest) {
relastFiles 'src/test/jastadd/multiple/Part1.relast', relast {
'src/test/jastadd/multiple/Part2.relast', inputFiles = [file('src/test/jastadd/multiple/Part1.relast'),
'src/test/jastadd/multiple/Part3.relast' file('src/test/jastadd/multiple/Part2.relast'),
file('src/test/jastadd/multiple/Part3.relast')]
grammarName = 'src/test/jastadd/multiple/Multiple' grammarName = 'src/test/jastadd/multiple/Multiple'
useJastAddNames = true useJastAddNames = true
noResolverHelper = true
}
jastadd {
packageName = 'multiple.ast' packageName = 'multiple.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
``` ```
The following options are supported, similar to the [command-line options](/../#supported-command-line-options): Please see the [documentation of the plugin][preprocessor-testing] for all options.
| Name | Description | Required | Default |
|-------------------|--------------------------------------------------------------------------------------------------------|--------------------|---------------------|
| `relastFiles` | Input grammar(s). Either one or multiple files separated by comma. | Yes | _none_ |
| `grammarName` | Directory and file prefix for the generated grammar and jrag created by RelAST. | Yes | _none_ |
| `useJastAddNames` | Set to `true` to use accessor names for relations matching JastAdd naming convention. | No | `false` |
| `packageName` | Name of the package for the Java files generated by JastAdd. | Yes (not enforced) | The empty package |
| `moreInputFiles` | Additional files as input for JastAdd. | No | No additional files |
| `resolverHelper` | Set to `true` to generate means for lazy resolving. | No | `false` |
| `jastAddList` | Alternative name for `List` nodes. Will be passed to both RelAST and JastAdd. | No | `List` |
| `serializer` | Name of supported serializer. One of {`jackson`, `jackson-json-pointer`, `jackson-manual-references`}. | No | No serializer |
## Test files ## Test files
...@@ -106,3 +100,4 @@ The workflow: ...@@ -106,3 +100,4 @@ The workflow:
[semantic-versioning]: https://semver.org/ [semantic-versioning]: https://semver.org/
[create-release]: /../-/tags/new [create-release]: /../-/tags/new
[create-issue]: https://git-st.inf.tu-dresden.de/jastadd/relational-rags/issues/new [create-issue]: https://git-st.inf.tu-dresden.de/jastadd/relational-rags/issues/new
[preprocessor-testing]: https://jastadd.pages.st.inf.tu-dresden.de/testing/
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
![RelAST process](relast-process.png) ![RelAST process](relast-process.png)
See [releases page](/../../releases) for the latest version. See [releases page](/../../releases) for the latest version and <https://jastadd.pages.st.inf.tu-dresden.de/relational-rags/> for more documentation.
The RelAST preprocessor takes a `.relast` file as input comprising AST rules and relations. It produces files that afterwards are processed by JastAdd to generated Java code. The RelAST preprocessor takes a `.relast` file as input comprising AST rules and relations. It produces files that afterwards are processed by JastAdd to generated Java code.
To use it in your project, build the JAR file running To use it in your project, build the JAR file running
...@@ -52,6 +52,7 @@ Note that you may have to change ...@@ -52,6 +52,7 @@ Note that you may have to change
## Supported relations ## Supported relations
```
// Directed relations // Directed relations
A.b -> B; A.b -> B;
A.b? -> B; A.b? -> B;
...@@ -70,3 +71,4 @@ Note that you may have to change ...@@ -70,3 +71,4 @@ Note that you may have to change
A.bs* <-> B.a; A.bs* <-> B.a;
A.bs* <-> B.a?; A.bs* <-> B.a?;
A.bs* <-> B.as*; A.bs* <-> B.as*;
```
import org.jastadd.relast.plugin.RelastTest buildscript {
repositories {
maven {
name "gitlab-maven"
url "https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven"
}
}
dependencies {
classpath 'org.jastadd.preprocessor:testing:0.2.14-32'
}
}
import org.jastadd.preprocessor.testing.plugin.PreprocessorPlugin
import org.jastadd.preprocessor.testing.plugin.RelastTest
//file:noinspection HardCodedStringLiteral
plugins {
id 'java'
id 'java-library'
id 'application'
id 'idea'
id 'maven-publish'
id 'org.jastadd' version '1.14.5'
}
apply plugin: 'java' apply plugin: PreprocessorPlugin
apply plugin: 'jastadd'
apply plugin: 'application'
apply plugin: "idea"
apply plugin: "org.jastadd.relast.plugin"
sourceCompatibility = 1.8 java.toolchain.languageVersion = JavaLanguageVersion.of(8)
ext {
mainClassName = 'org.jastadd.relast.compiler.Compiler' mainClassName = 'org.jastadd.relast.compiler.Compiler'
}
repositories { repositories {
jcenter() mavenCentral()
maven {
name 'gitlab-maven'
url 'https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven'
}
} }
group = 'org.jastadd' group = 'org.jastadd'
apply plugin: 'maven-publish'
buildscript { // set the main class name for `gradle run`
repositories.jcenter() application.mainClass = "${mainClassName}"
dependencies {
classpath 'org.jastadd:jastaddgradle:1.13.3'
}
}
dependencies { dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
testCompile 'org.assertj:assertj-core:3.12.1' testImplementation 'org.assertj:assertj-core:3.22.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.8' testImplementation 'com.fasterxml.jackson.core:jackson-core:2.13.1'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8' testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.13.1'
compile 'org.jastadd:jastadd:2.3.4' api 'org.jastadd:jastadd:2.3.5'
runtime 'org.jastadd:jastadd:2.3.4' api 'net.sf.beaver:beaver-rt:0.9.11'
compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0'
}
sourceSets {
main {
java.srcDir "src/gen/java"
java.srcDir "buildSrc/gen/java"
}
test {
java.srcDir "src/test/java-gen"
}
} }
File genSrc = file('src/gen/java')
File testGenSrc = file('src/test/java-gen')
sourceSets.main.java.srcDir genSrc
sourceSets.test.java.srcDir testGenSrc
idea.module.generatedSourceDirs += genSrc
idea.module.generatedSourceDirs += testGenSrc
def versionFile = 'src/main/resources/RelASTVersion.properties' def versionFile = 'src/main/resources/RelASTVersion.properties'
def oldProps = new Properties()
try { try {
def oldProps = new Properties()
file(versionFile).withInputStream { stream -> oldProps.load(stream) } file(versionFile).withInputStream { stream -> oldProps.load(stream) }
version = oldProps['version'] version = oldProps['version']
} catch (e) { } catch (ignored) {
// this happens, if either the properties file is not present, or cannot be read from // this happens, if either the properties file is not present, or cannot be read from
throw new GradleException("File ${versionFile} not found or unreadable. Aborting.") throw new GradleException("File ${versionFile} not found or unreadable. Aborting.")
} }
...@@ -66,13 +81,33 @@ task newVersion() { ...@@ -66,13 +81,33 @@ task newVersion() {
} }
} }
jar { task printVersion() {
manifest { doLast {
attributes "Main-Class": 'org.jastadd.relast.compiler.Compiler' println(version)
}
} }
task setDevVersionForCI() {
doFirst {
def props = new Properties()
props['version'] = version + "-$System.env.CI_PIPELINE_IID"
props.store(file(versionFile).newWriter(), null)
}
}
jar.archiveBaseName = 'relast'
task fatJar(type: Jar) {
dependsOn jar
group = "build"
archiveBaseName = 'relast'
archiveAppendix = "fatjar"
from sourceSets.main.output
from { from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
manifest {
attributes "Main-Class": "${mainClassName}"
} }
} }
...@@ -80,94 +115,95 @@ jastadd { ...@@ -80,94 +115,95 @@ jastadd {
configureModuleBuild() configureModuleBuild()
modules { modules {
//noinspection GroovyAssignabilityCheck //noinspection GroovyAssignabilityCheck
module("RelAst") { module('RelAst') {
java {
basedir "."
include "src/main/**/*.java"
include "src/gen/**/*.java"
}
jastadd { jastadd {
basedir "src/main/jastadd/" basedir 'src/main/jastadd/'
include "**/*.ast" include '**/*.ast'
include "**/*.jadd" include '**/*.jadd'
include "**/*.jrag" include '**/*.jrag'
} }
scanner { scanner {
include "src/main/jastadd/RelAst.flex" include 'src/main/jastadd/RelAst.flex'
} }
parser { parser {
include "src/main/jastadd/Preamble.parser" include 'src/main/jastadd/Preamble.parser'
include "src/main/jastadd/RelAst.parser" include 'src/main/jastadd/RelAst.parser'
} }
} }
} }
cleanGen.doFirst { cleanGen.doFirst {
delete "src/gen/java/org" delete 'src/gen/'
delete "src/gen-res/BuildInfo.properties" delete 'src/gen-res/'
} }
preprocessParser.doFirst { preprocessParser.doFirst {
args += ["--no-beaver-symbol"] args += ["--no-beaver-symbol"]
} }
module = "RelAst" module = 'RelAst'
astPackage = 'org.jastadd.relast.ast' astPackage = 'org.jastadd.relast.ast'
parser.name = 'RelAstParser' parser.name = 'RelAstParser'
genDir = 'src/gen/java' genDir = 'src/gen/java'
buildInfoDir = 'src/gen-res' buildInfoDir = 'src/gen-res'
scanner.genDir = 'src/gen/java/org/jastadd/relast/scanner'
parser.genDir = 'src/gen/java/org/jastadd/relast/parser'
scanner.genDir = "src/gen/java/org/jastadd/relast/scanner" // default options are: ['--rewrite=cnta', '--safeLazy', '--visitCheck=false', '--cacheCycle=false']
parser.genDir = "src/gen/java/org/jastadd/relast/parser" extraJastAddOptions = ['--lineColumnNumbers', '--visitCheck=true']
jastaddOptions = ["--lineColumnNumbers", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
} }
// publish gitlab project
publishing { publishing {
publications { publications {
maven(MavenPublication) { maven(MavenPublication) {
artifact("build/libs/relast-${version}.jar") { artifactId = 'relast'
extension 'jar' from components.java
}
} }
} }
repositories { repositories {
maven { maven {
name 'nexus' url "https://git-st.inf.tu-dresden.de/api/v4/projects/$System.env.CI_PROJECT_ID/packages/maven"
url "http://172.22.1.152:8081/repository/" + (project.hasProperty('asSnapshot') ? "maven-snapshots" : "maven-releases/") credentials(HttpHeaderCredentials) {
credentials { name = 'Job-Token'
username project.ext.properties.repoUser value = System.getenv('CI_JOB_TOKEN')
password project.ext.properties.repoPassword
}
} }
authentication {
header(HttpHeaderAuthentication)
} }
} }
publish.dependsOn jar }
}
task firstRelationsRun(type: RelastTest) { task firstRelationsRun(type: RelastTest) {
relastFiles 'src/test/jastadd/relations/Relations.relast' relast {
inputFiles = [file('src/test/jastadd/relations/Relations.relast')]
grammarName = 'src/test/jastadd/relations/Relations' grammarName = 'src/test/jastadd/relations/Relations'
useJastAddNames = true useJastAddNames = true
noResolverHelper = true
}
jastadd {
packageName = 'relations.ast' packageName = 'relations.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/relations/Relations.jrag' inputFiles = [file('src/test/jastadd/Utils.jadd'),
file('src/test/jastadd/relations/Relations.jrag')]
}
} }
task secondRelationsRun(type: RelastTest, dependsOn: firstRelationsRun) { task secondRelationsRun(type: RelastTest, dependsOn: firstRelationsRun) {
relastFiles 'src/test/jastadd/relations/Relations.ast' relast {
inputFiles = [file('src/test/jastadd/relations/Relations.ast')]
grammarName = 'src/test/jastadd/relations/Relations2' grammarName = 'src/test/jastadd/relations/Relations2'
useJastAddNames = true useJastAddNames = true
noResolverHelper = true
}
jastadd {
skipRun = true
packageName = 'ignored' packageName = 'ignored'
}
doLast { doLast {
delete fileTree('src/test/java-gen/ignored') delete fileTree('src/test/java-gen/ignored')
...@@ -176,131 +212,198 @@ task secondRelationsRun(type: RelastTest, dependsOn: firstRelationsRun) { ...@@ -176,131 +212,198 @@ task secondRelationsRun(type: RelastTest, dependsOn: firstRelationsRun) {
} }
task compileConstructorTest(type: RelastTest) { task compileConstructorTest(type: RelastTest) {
relastFiles 'src/test/jastadd/constructors/Constructors.relast' relast {
inputFiles = [file('src/test/jastadd/constructors/Constructors.relast')]
grammarName = 'src/test/jastadd/constructors/Constructors' grammarName = 'src/test/jastadd/constructors/Constructors'
noResolverHelper = true
}
jastadd {
packageName = 'constructors.ast' packageName = 'constructors.ast'
moreInputFiles 'src/test/jastadd/constructors/Constructors.jrag' inputFiles = [file('src/test/jastadd/constructors/Constructors.jrag')]
}
} }
task compileDefaultNamesTest(type: RelastTest) { task compileDefaultNamesTest(type: RelastTest) {
relastFiles 'src/test/jastadd/relations/Relations.relast' relast {
inputFiles = [file('src/test/jastadd/relations/Relations.relast')]
grammarName = 'src/test/jastadd/relations/Relations3' grammarName = 'src/test/jastadd/relations/Relations3'
useJastAddNames = false
noResolverHelper = true
}
jastadd {
packageName = 'defaultnames.ast' packageName = 'defaultnames.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/relations/Relations.jrag' inputFiles = [file('src/test/jastadd/Utils.jadd'),
file('src/test/jastadd/relations/Relations.jrag')]
}
} }
task compileDefaultNamesResolverTest(type: RelastTest) { task compileDefaultNamesResolverTest(type: RelastTest) {
relastFiles 'src/test/jastadd/resolver/Resolver.relast' relast {
inputFiles = [file('src/test/jastadd/resolver/Resolver.relast')]
grammarName = 'src/test/jastadd/resolver/Resolver2' grammarName = 'src/test/jastadd/resolver/Resolver2'
resolverHelper = true useJastAddNames = false
}
jastadd {
packageName = 'defaultnames.resolver.ast' packageName = 'defaultnames.resolver.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', inputFiles = [file('src/test/jastadd/Utils.jadd'),
'src/test/jastadd/resolver/ResolverUtils.jadd', file('src/test/jastadd/resolver/ResolverUtils.jadd'),
'src/test/jastadd/resolver/MyRefResolver.jadd' file('src/test/jastadd/resolver/MyRefResolver.jadd')]
}
} }
task compileLowerBoundsTest(type: RelastTest) { task compileLowerBoundsTest(type: RelastTest) {
relastFiles 'src/test/jastadd/lowerbounds/LowerBounds.relast' relast {
inputFiles = [file('src/test/jastadd/lowerbounds/LowerBounds.relast')]
grammarName = 'src/test/jastadd/lowerbounds/LowerBounds' grammarName = 'src/test/jastadd/lowerbounds/LowerBounds'
useJastAddNames = true useJastAddNames = true
noResolverHelper = true
}
jastadd {
packageName = 'lowerbounds.ast' packageName = 'lowerbounds.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
task compileMultipleTest(type: RelastTest) { task compileMultipleTest(type: RelastTest) {
relastFiles 'src/test/jastadd/multiple/Part1.relast', relast {
'src/test/jastadd/multiple/Part2.relast', inputFiles = [file('src/test/jastadd/multiple/Part1.relast'),
'src/test/jastadd/multiple/Part3.relast' file('src/test/jastadd/multiple/Part2.relast'),
file('src/test/jastadd/multiple/Part3.relast')]
grammarName = 'src/test/jastadd/multiple/Multiple' grammarName = 'src/test/jastadd/multiple/Multiple'
useJastAddNames = true useJastAddNames = true
noResolverHelper = true
}
jastadd {
packageName = 'multiple.ast' packageName = 'multiple.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
task compileMultipleMixedTest(type: RelastTest) { task compileMultipleMixedTest(type: RelastTest) {
relastFiles 'src/test/jastadd/multiple-mixed/Part1.relast', relast {
'src/test/jastadd/multiple-mixed/Part2.relast', inputFiles = [file('src/test/jastadd/multiple-mixed/Part1.relast'),
'src/test/jastadd/multiple-mixed/Part3.relast' file('src/test/jastadd/multiple-mixed/Part2.relast'),
file('src/test/jastadd/multiple-mixed/Part3.relast')]
grammarName = 'src/test/jastadd/multiple/Multiple' grammarName = 'src/test/jastadd/multiple/Multiple'
useJastAddNames = true useJastAddNames = true
noResolverHelper = true
}
jastadd {
packageName = 'mixed.multiple.ast' packageName = 'mixed.multiple.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
task compileResolverTest(type: RelastTest) { task compileResolverTest(type: RelastTest) {
relastFiles 'src/test/jastadd/resolver/Resolver.relast' relast {
inputFiles = [file('src/test/jastadd/resolver/Resolver.relast')]
grammarName = 'src/test/jastadd/resolver/Resolver' grammarName = 'src/test/jastadd/resolver/Resolver'
useJastAddNames = true useJastAddNames = true
resolverHelper = true }
jastadd {
packageName = 'resolver.ast' packageName = 'resolver.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', inputFiles = [file('src/test/jastadd/Utils.jadd'),
'src/test/jastadd/resolver/ResolverUtils.jadd', file('src/test/jastadd/resolver/ResolverUtils.jadd'),
'src/test/jastadd/resolver/MyRefResolver.jadd' file('src/test/jastadd/resolver/MyRefResolver.jadd')]
}
} }
task compileResolver2Test(type: RelastTest) { task compileResolver2Test(type: RelastTest) {
relastFiles 'src/test/jastadd/resolver2/Resolver.relast' relast {
inputFiles = [file('src/test/jastadd/resolver2/Resolver.relast')]
grammarName = 'src/test/jastadd/resolver2/Resolver' grammarName = 'src/test/jastadd/resolver2/Resolver'
useJastAddNames = true useJastAddNames = true
resolverHelper = true }
jastadd {
packageName = 'resolver2.ast' packageName = 'resolver2.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', inputFiles = [file('src/test/jastadd/Utils.jadd'),
'src/test/jastadd/resolver2/ResolverUtils.jadd', file('src/test/jastadd/resolver2/ResolverUtils.jadd'),
'src/test/jastadd/resolver2/MyRefResolver.jadd' file('src/test/jastadd/resolver2/MyRefResolver.jadd')]
}
} }
task compileListNamesTest(type: RelastTest) { task compileListNamesTest(type: RelastTest) {
relastFiles 'src/test/jastadd/listnames/ListNames.relast' relast {
inputFiles = [file('src/test/jastadd/listnames/ListNames.relast')]
grammarName = 'src/test/jastadd/listnames/ListNames' grammarName = 'src/test/jastadd/listnames/ListNames'
useJastAddNames = true useJastAddNames = true
jastAddList = 'ListyMcListface' noResolverHelper = true
listClass = 'java.util.LinkedList' listClass = 'java.util.LinkedList'
}
jastadd {
jastAddList = 'ListyMcListface'
packageName = 'listnames.ast' packageName = 'listnames.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
task compileSerializerTest(type: RelastTest) { task compileSerializerTest(type: RelastTest) {
relastFiles 'src/test/jastadd/serializer/Serializer.relast' relast {
inputFiles = [file('src/test/jastadd/serializer/Serializer.relast')]
grammarName = 'src/test/jastadd/serializer/Serializer' grammarName = 'src/test/jastadd/serializer/Serializer'
useJastAddNames = true useJastAddNames = true
serializer = 'jackson' serializer = 'jackson'
noResolverHelper = true
}
jastadd {
packageName = 'serializer.ast' packageName = 'serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
task compileSerializerDefaultNamesTest(type: RelastTest) { task compileSerializerDefaultNamesTest(type: RelastTest) {
relastFiles 'src/test/jastadd/serializer-names/Serializer.relast' relast {
inputFiles = [file('src/test/jastadd/serializer-names/Serializer.relast')]
grammarName = 'src/test/jastadd/serializer-names/Serializer' grammarName = 'src/test/jastadd/serializer-names/Serializer'
serializer = 'jackson' serializer = 'jackson'
useJastAddNames = false
noResolverHelper = true
}
jastadd {
packageName = 'defaultnames.serializer.ast' packageName = 'defaultnames.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
task compileSerializerPointerTest(type: RelastTest) { task compileSerializerPointerTest(type: RelastTest) {
resolverHelper = true relast {
relastFiles 'src/test/jastadd/serializer-pointer/Serializer.relast' inputFiles = [file('src/test/jastadd/serializer-pointer/Serializer.relast')]
grammarName = 'src/test/jastadd/serializer-pointer/Serializer' grammarName = 'src/test/jastadd/serializer-pointer/Serializer'
serializer = 'jackson-json-pointer' serializer = 'jackson-json-pointer'
useJastAddNames = false
}
jastadd {
packageName = 'pointer.serializer.ast' packageName = 'pointer.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd' inputFiles = [file('src/test/jastadd/Utils.jadd')]
}
} }
task compileSerializerManualTest(type: RelastTest) { task compileSerializerManualTest(type: RelastTest) {
resolverHelper = true relast {
relastFiles 'src/test/jastadd/serializer-manual/Serializer.relast' inputFiles = [file('src/test/jastadd/serializer-manual/Serializer.relast')]
grammarName = 'src/test/jastadd/serializer-manual/Serializer' grammarName = 'src/test/jastadd/serializer-manual/Serializer'
serializer = 'jackson-manual-references' serializer = 'jackson-manual-references'
useJastAddNames = false
}
jastadd {
packageName = 'manual.serializer.ast' packageName = 'manual.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/serializer-manual/JsonPointer.jrag' inputFiles = [file('src/test/jastadd/Utils.jadd'),
file('src/test/jastadd/serializer-manual/JsonPointer.jrag')]
}
} }
task compileSerializerManualRelativeTest(type: RelastTest) { task compileSerializerManualRelativeTest(type: RelastTest) {
resolverHelper = true relast {
relastFiles 'src/test/jastadd/serializer-manual-relative/Serializer.relast' inputFiles = [file('src/test/jastadd/serializer-manual-relative/Serializer.relast')]
grammarName = 'src/test/jastadd/serializer-manual-relative/Serializer' grammarName = 'src/test/jastadd/serializer-manual-relative/Serializer'
serializer = 'jackson-manual-references' serializer = 'jackson-manual-references'
useJastAddNames = false
}
jastadd {
packageName = 'manual.relative.serializer.ast' packageName = 'manual.relative.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/serializer-manual-relative/JsonPointer.jrag' inputFiles = [file('src/test/jastadd/Utils.jadd'),
file('src/test/jastadd/serializer-manual-relative/JsonPointer.jrag')]
}
} }
task cleanTestGen(type: Delete) { task cleanTestGen(type: Delete) {
......
package org.jastadd.relast.plugin;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskCollection;
import java.util.Set;
/**
* Plugin for RelAst-Test.
*
* @author rschoene - Initial contribution
*/
public class RelastPlugin implements Plugin<Project> {
private Task testTask;
@Override
public void apply(Project project) {
Set<Task> tasks = project.getTasksByName("test", false);
// there should be only one task "test"
testTask = tasks.iterator().next();
TaskCollection<RelastTest> relastTests = project.getTasks().withType(RelastTest.class);
relastTests.forEach(this::setupRelastTest);
relastTests.whenTaskAdded(this::setupRelastTest);
}
private void setupRelastTest(RelastTest relastTest) {
testTask.dependsOn(relastTest);
relastTest.setGroup("verification");
}
}
package org.jastadd.relast.plugin;
import org.gradle.api.DefaultTask;
import org.gradle.api.Project;
import org.gradle.api.file.FileCollection;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskAction;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* RelAst Test Task
*
* @author rschoene - Initial contribution
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class RelastTest extends DefaultTask {
// general options
private boolean verbose = false;
// pre-process options
private List<String> relastFiles = new ArrayList<>();
private boolean useJastAddNames;
private boolean resolverHelper;
private boolean writeToFile = true;
private String grammarName;
private String listClass;
private String jastAddList;
private String serializer;
// compile options
private boolean runJastAdd = true;
private String outputDir = "src/test/java-gen/";
private String packageName;
private List<String> moreInputFiles = new ArrayList<>();
public boolean isVerbose() {
return verbose;
}
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
// pre-process options
public List<String> getRelastFiles() {
return relastFiles;
}
public void relastFiles(String relastFile) {
this.relastFiles.add(relastFile);
}
public void relastFiles(String[] relastFilesArray) {
this.relastFiles = Arrays.asList(relastFilesArray);
}
public boolean isUseJastAddNames() {
return useJastAddNames;
}
public void setUseJastAddNames(boolean useJastAddNames) {
this.useJastAddNames = useJastAddNames;
}
public boolean isResolverHelper() {
return resolverHelper;
}
public void setResolverHelper(boolean resolverHelper) {
this.resolverHelper = resolverHelper;
}
public boolean isWriteToFile() {
return writeToFile;
}
public void setWriteToFile(boolean writeToFile) {
this.writeToFile = writeToFile;
}
public String getGrammarName() {
return grammarName;
}
public void setGrammarName(String grammarName) {
this.grammarName = grammarName;
}
public String getListClass() {
return listClass;
}
public void setListClass(String listClass) {
this.listClass = listClass;
}
public String getJastAddList() {
return jastAddList;
}
public void setJastAddList(String jastAddList) {
this.jastAddList = jastAddList;
}
public String getSerializer() {
return serializer;
}
public void setSerializer(String serializer) {
this.serializer = serializer;
}
// compile options
public boolean isRunJastAdd() {
return runJastAdd;
}
public void setRunJastAdd(boolean runJastAdd) {
this.runJastAdd = runJastAdd;
}
public String getOutputDir() {
return outputDir;
}
public void setOutputDir(String outputDir) {
this.outputDir = outputDir;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public List<String> getMoreInputFiles() {
return moreInputFiles;
}
public void moreInputFiles(String f) {
this.moreInputFiles.add(f);
}
public void moreInputFiles(String[] fileArray) {
this.moreInputFiles.addAll(Arrays.asList(fileArray));
}
private boolean isSet(String option) {
return option != null && !option.isEmpty();
}
private String[] genSuffixes = {".ast", ".jadd", "RefResolver.jadd", "ResolverStubs.jrag", "Serializer.jadd"};
@TaskAction
void runTest() {
setGroup("verification");
setDescription("Runs a relast test");
Project project = getProject();
if (isVerbose()) {
System.out.println("Running relast test");
System.out.println("relast files: " + getRelastFiles());
System.out.println("Deleting files");
}
// first, delete generated files
List<String> genFiles = new ArrayList<>();
for (String suffix : genSuffixes) {
genFiles.add(getGrammarName() + suffix);
}
if (isVerbose()) {
System.out.println("gen files: " + genFiles);
}
project.delete(deleteSpec -> {
deleteSpec.delete(genFiles);
if (isSet(getPackageName())) {
deleteSpec.delete(Paths.get(getOutputDir(), getPackageName()));
}
});
if (isVerbose()) {
System.out.println("Pre processing, running relast");
}
// then, run relast pre processing
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
project.javaexec(javaExecSpec -> {
javaExecSpec.setClasspath(runtimeClasspath);
javaExecSpec.setMain("org.jastadd.relast.compiler.Compiler");
List<Object> args = new ArrayList<>(getRelastFiles());
args.add("--quiet");
if (isWriteToFile()) {
args.add("--file");
}
if (isUseJastAddNames()) {
args.add("--useJastAddNames");
}
if (isResolverHelper()) {
args.add("--resolverHelper");
}
if (isSet(getJastAddList())) {
args.add("--jastAddList=" + getJastAddList());
}
if (isSet(getListClass())) {
args.add("--listClass=" + getListClass());
}
if (isSet(getSerializer())) {
args.add("--serializer=" + getSerializer());
}
args.add("--grammarName=" + getGrammarName());
if (isVerbose()) {
System.out.println("Start relast with args: " + args);
}
javaExecSpec.args(args);
});
});
if (isRunJastAdd()) {
if (isVerbose()) {
System.out.println("Compile with JastAdd");
}
// check which files were actually generated
genFiles.removeIf(s -> !Paths.get(s).toFile().exists());
// finally, compile generated files
project.getPlugins().withType(JavaPlugin.class, javaPlugin -> {
SourceSetContainer sourceSets = (SourceSetContainer) project.getProperties().get("sourceSets");
FileCollection runtimeClasspath = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath();
project.javaexec(javaExecSpec -> {
javaExecSpec.setClasspath(runtimeClasspath);
javaExecSpec.setMain("org.jastadd.JastAdd");
List<Object> args = new ArrayList<>();
args.add("--o=" + getOutputDir());
args.add("--package=" + getPackageName());
if (isSet(getJastAddList())) {
args.add("--List=" + getJastAddList());
}
args.addAll(genFiles);
args.addAll(getMoreInputFiles());
if (isVerbose()) {
System.out.println("Start JastAdd with args: " + args);
}
javaExecSpec.args(args);
});
});
}
}
}
implementation-class=org.jastadd.relast.plugin.RelastPlugin
No preview for this file type
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
#!/usr/bin/env sh #!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
############################################################################## ##############################################################################
## ##
## Gradle start up script for UN*X ## Gradle start up script for UN*X
...@@ -28,7 +44,7 @@ APP_NAME="Gradle" ...@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS="" DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
...@@ -66,6 +82,7 @@ esac ...@@ -66,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
...@@ -109,10 +126,11 @@ if $darwin; then ...@@ -109,10 +126,11 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if $cygwin ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
...@@ -138,19 +156,19 @@ if $cygwin ; then ...@@ -138,19 +156,19 @@ if $cygwin ; then
else else
eval `echo args$i`="\"$arg\"" eval `echo args$i`="\"$arg\""
fi fi
i=$((i+1)) i=`expr $i + 1`
done done
case $i in case $i in
(0) set -- ;; 0) set -- ;;
(1) set -- "$args0" ;; 1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;; 2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;; 3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
...@@ -159,14 +177,9 @@ save () { ...@@ -159,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " " echo " "
} }
APP_ARGS=$(save "$@") APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules # Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@" exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
...@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. ...@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS= set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
...@@ -35,7 +54,7 @@ goto fail ...@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
...@@ -45,28 +64,14 @@ echo location of your Java installation. ...@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
......
rootProject.name = 'RelAST'
...@@ -97,19 +97,20 @@ aspect ComponentAnalysis { ...@@ -97,19 +97,20 @@ aspect ComponentAnalysis {
// find a matching component on the RHS of the (current) super type // find a matching component on the RHS of the (current) super type
Component c = findComponent(td, getID()); Component c = findComponent(td, getID());
if (c != null && !this.isEqual(c)) return c; if (c != null && !this.usesSameTypeAs(c)) return c;
} }
return null; return null;
} }
//--- isEqual --- //--- usesSameTypeAs ---
syn boolean Component.isEqual(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse()); syn boolean Component.usesSameTypeAs(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse());
/** /**
* TokenComponents may be specialized by NTATokenComponents and vice versa * TokenComponents may be specialized by NTATokenComponents and vice versa
*/ */
eq TokenComponent.isEqual(Component c) = (c instanceof TokenComponent) && getTypeUse().isEqual(c.getTypeUse()); eq TokenComponent.usesSameTypeAs(Component c) = (c instanceof TokenComponent) && getTypeUse().isEqual(c.getTypeUse());
// --- isEqual ---
syn boolean TypeUse.isEqual(TypeUse u); syn boolean TypeUse.isEqual(TypeUse u);
eq SimpleTypeUse.isEqual(TypeUse u) = u instanceof SimpleTypeUse && getID().equals(u.getID()); eq SimpleTypeUse.isEqual(TypeUse u) = u instanceof SimpleTypeUse && getID().equals(u.getID());
eq ParameterizedTypeUse.isEqual(TypeUse u) { eq ParameterizedTypeUse.isEqual(TypeUse u) {
...@@ -123,6 +124,8 @@ aspect ComponentAnalysis { ...@@ -123,6 +124,8 @@ aspect ComponentAnalysis {
return true; return true;
} }
syn boolean Component.isEqual(Component other) = this.usesSameTypeAs(other) && this.getID().equals(other.getID());
//--- matches --- //--- matches ---
/** /**
* @return true, if the component has both type and role, its type matches the given typeDecl and its name matches the given name * @return true, if the component has both type and role, its type matches the given typeDecl and its name matches the given name
...@@ -160,12 +163,40 @@ aspect ComponentAnalysis { ...@@ -160,12 +163,40 @@ aspect ComponentAnalysis {
return set; return set;
} }
//--- needUnresolvedClass --- /**
syn boolean TypeDecl.needUnresolvedClass() { * @return a set of all types that refer to this type using a non-containment relation
// a TypeDecl needs an unresolved class, if it can appear in a relation */
// TODO coll Set<TypeDecl> TypeDecl.referencingTypes() [new HashSet<TypeDecl>()];
RelationComponent contributes opposite().getTypeUse().decl()
when opposite().isNavigable()
to TypeDecl.referencingTypes()
for getTypeUse().decl();
/**
* @return true, if the type can be the target of a non-containment relation
*/
syn boolean TypeDecl.isReferenceTarget() {
return !referencingTypes().isEmpty();
}
/**
* @return true, if the type or one of its abstract supertypes can be the target of a non-containment relation
*/
syn boolean TypeDecl.requiresUresolvedClass() {
if (referencingTypes().isEmpty()) {
// if the type is not referenced itself, it may still be required by an abstract supertype that is referenced
TypeDecl decl = this;
while (decl.hasSuper()) {
decl = decl.getSuper().decl();
if (decl.getAbstract() && !decl.referencingTypes().isEmpty()) {
return true; return true;
} }
}
return false;
} else {
return true;
}
}
//--- isList --- //--- isList ---
syn boolean Component.isList() = false; syn boolean Component.isList() = false;
...@@ -201,6 +232,8 @@ aspect InstanceSupplier { ...@@ -201,6 +232,8 @@ aspect InstanceSupplier {
return subDecls; return subDecls;
} }
syn boolean TypeDecl.instantiable() = instantiableSubType() != null;
//--- instantiableSubType --- //--- instantiableSubType ---
syn TypeDecl TypeDecl.instantiableSubType() { syn TypeDecl TypeDecl.instantiableSubType() {
if (getAbstract() == false) { if (getAbstract() == false) {
...@@ -225,14 +258,20 @@ aspect Constructors { ...@@ -225,14 +258,20 @@ aspect Constructors {
//--- componentsTransitive --- //--- componentsTransitive ---
syn Collection<Component> TypeDecl.componentsTransitive() { syn Collection<Component> TypeDecl.componentsTransitive() {
ArrayList<Component> list = new ArrayList<>(); ArrayList<Component> list = new ArrayList<>();
if (hasSuper() && getSuper().decl() != null) {
list.addAll(getSuper().decl().componentsTransitive());
}
for (Component c: getComponents()) { for (Component c: getComponents()) {
if (c.inConstructor()) { if (c.inConstructor()) {
list.add(c); list.add(c);
} }
} }
int insertionIndex = 0;
if (hasSuper() && getSuper().decl() != null) {
for (Component c : getSuper().decl().componentsTransitive()) {
if (!list.stream().anyMatch(c::isEqual)) {
list.add(insertionIndex, c);
insertionIndex++;
}
}
}
return list; return list;
} }
......
...@@ -79,8 +79,8 @@ Component component = ...@@ -79,8 +79,8 @@ Component component =
// NTA // NTA
| SLASH ID COL s_type_use.u SLASH {: return new NTAComponent(ID, u); :} | SLASH ID COL s_type_use.u SLASH {: return new NTAComponent(ID, u); :}
| SLASH s_type_use.u SLASH {: return new NTAComponent(u.getID(), u); :} | SLASH s_type_use.u SLASH {: return new NTAComponent(u.getID(), u); :}
// NTA Token (same as NTA) // NTA Token
| SLASH LT ID COL s_type_use.u GT SLASH {: return new NTATokenComponent(ID, u); :} | SLASH LT ID COL type_use.u GT SLASH {: return new NTATokenComponent(ID, u); :}
| SLASH LT ID GT SLASH {: return new NTATokenComponent(ID, new SimpleTypeUse("String")); :} | SLASH LT ID GT SLASH {: return new NTATokenComponent(ID, new SimpleTypeUse("String")); :}
// Token // Token
| LT ID COL type_use.u GT {: return new TokenComponent(ID, u); :} | LT ID COL type_use.u GT {: return new TokenComponent(ID, u); :}
......
...@@ -149,8 +149,10 @@ aspect NameResolutionHelper { ...@@ -149,8 +149,10 @@ aspect NameResolutionHelper {
sb.append("aspect ReferenceCreation {\n\n"); sb.append("aspect ReferenceCreation {\n\n");
for (TypeDecl decl : getTypeDeclList()) { for (TypeDecl decl : getTypeDeclList()) {
if (decl.isReferenceTarget()) {
decl.createReferenceCreator(sb); decl.createReferenceCreator(sb);
} }
}
sb.append("}\n\n"); sb.append("}\n\n");
...@@ -172,7 +174,7 @@ aspect NameResolutionHelper { ...@@ -172,7 +174,7 @@ aspect NameResolutionHelper {
sb.append(ind(1) + "}\n\n"); sb.append(ind(1) + "}\n\n");
for (TypeDecl td: getTypeDecls()) { for (TypeDecl td: getTypeDecls()) {
if (td.needUnresolvedClass()) { if (td.requiresUresolvedClass()) {
td.generateUnresolvedClass(sb); td.generateUnresolvedClass(sb);
} }
} }
...@@ -182,11 +184,10 @@ aspect NameResolutionHelper { ...@@ -182,11 +184,10 @@ aspect NameResolutionHelper {
public void TypeDecl.createReferenceCreator(StringBuilder sb) { public void TypeDecl.createReferenceCreator(StringBuilder sb) {
if (!instantiable()) {
System.out.println("WARNING: unable to find instantiable subtype for " + getID() + "! Skipping the creation of reference creator methods.");
} else {
TypeDecl instantiableSubType = instantiableSubType(); TypeDecl instantiableSubType = instantiableSubType();
if (instantiableSubType == null) {
throw new RuntimeException("unable to find instantiable subtype for " + getID());
}
sb.append(ind(1) + "public static " + getID() + " " + getID() + "." + createRefMethod + "(String ref) {\n"); sb.append(ind(1) + "public static " + getID() + " " + getID() + "." + createRefMethod + "(String ref) {\n");
sb.append(ind(2) + unresolvedPrefix + instantiableSubType.getID() + " unresolvedNode = new " + unresolvedPrefix + instantiableSubType.getID() + "();\n"); sb.append(ind(2) + unresolvedPrefix + instantiableSubType.getID() + " unresolvedNode = new " + unresolvedPrefix + instantiableSubType.getID() + "();\n");
sb.append(ind(2) + "unresolvedNode.set" + unresolvedPrefix + "Token(ref);\n"); sb.append(ind(2) + "unresolvedNode.set" + unresolvedPrefix + "Token(ref);\n");
...@@ -201,6 +202,7 @@ aspect NameResolutionHelper { ...@@ -201,6 +202,7 @@ aspect NameResolutionHelper {
sb.append(ind(2) + "return unresolvedNode;\n"); sb.append(ind(2) + "return unresolvedNode;\n");
sb.append(ind(1) + "}\n"); sb.append(ind(1) + "}\n");
} }
}
public void TypeDecl.generateContextIndependentNameResolution(StringBuilder sb) { public void TypeDecl.generateContextIndependentNameResolution(StringBuilder sb) {
sb.append(ind(1) + "// context-independent name resolution\n"); sb.append(ind(1) + "// context-independent name resolution\n");
......
...@@ -268,6 +268,9 @@ aspect Serializer { ...@@ -268,6 +268,9 @@ aspect Serializer {
public void TypeDecl.deserialize(StringBuilder sb) { public void TypeDecl.deserialize(StringBuilder sb) {
sb.append(ind(1) + "public static " + getID() + " " + getID() + ".deserialize(java.io.File file) throws DeserializationException {\n"); sb.append(ind(1) + "public static " + getID() + " " + getID() + ".deserialize(java.io.File file) throws DeserializationException {\n");
if (instantiable()) {
sb.append(ind(2) + "try {\n"); sb.append(ind(2) + "try {\n");
sb.append(ind(3) + "com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();\n"); sb.append(ind(3) + "com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonFactory factory = mapper.getFactory();\n"); sb.append(ind(3) + "com.fasterxml.jackson.core.JsonFactory factory = mapper.getFactory();\n");
...@@ -329,6 +332,9 @@ aspect Serializer { ...@@ -329,6 +332,9 @@ aspect Serializer {
} }
sb.append(ind(2) + "return element;\n"); sb.append(ind(2) + "return element;\n");
} else {
sb.append(ind(2) + "throw new DeserializationException(\"Unable to deserialize type \\\"" + getID() + "\\\" because it is not instantiable.\");\n");
}
sb.append(ind(1) + "}\n"); sb.append(ind(1) + "}\n");
} }
...@@ -586,7 +592,7 @@ aspect Serializer { ...@@ -586,7 +592,7 @@ aspect Serializer {
sb.append(ind(3) + "if (map.keySet().contains(unique$Id())) {\n"); sb.append(ind(3) + "if (map.keySet().contains(unique$Id())) {\n");
sb.append(ind(4) + "throw new RuntimeException(new SerializationException(\"UID \" + this.unique$Id() + \" is assigned to both \" + this.getClass().getSimpleName() + \":\" + this.hashCode() + \" and \" + map.get(unique$Id()).getClass().getSimpleName() + \":\" + map.get(unique$Id()).hashCode()));\n"); sb.append(ind(4) + "throw new RuntimeException(new SerializationException(\"UID \" + this.unique$Id() + \" is assigned to both \" + this.getClass().getSimpleName() + \":\" + this.hashCode() + \" and \" + map.get(unique$Id()).getClass().getSimpleName() + \":\" + map.get(unique$Id()).hashCode()));\n");
sb.append(ind(3) + "} else {\n"); sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "map.put(this.unique$Id, new java.lang.ref.WeakReference(this));\n"); sb.append(ind(4) + "map.put(this.unique$Id(), new java.lang.ref.WeakReference(this));\n");
sb.append(ind(3) + "}\n"); sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n"); sb.append(ind(2) + "}\n");
sb.append(ind(2) + "for (ASTNode child : astChildren()) {\n"); sb.append(ind(2) + "for (ASTNode child : astChildren()) {\n");
......
#Thu Apr 16 11:22:48 CEST 2020 #Fri Mar 11 17:24:51 CET 2022
version=0.3.0 version=0.4.0
...@@ -3,6 +3,7 @@ S ::= S1:A S2:A* [S3:A] /S4:A/ /S5:A*/ /[S6:A]/ /<S7>/ /<S8:long>/; ...@@ -3,6 +3,7 @@ S ::= S1:A S2:A* [S3:A] /S4:A/ /S5:A*/ /[S6:A]/ /<S7>/ /<S8:long>/;
B : S ::= B1:A B2:A* [B3:A] /B4:A/ /B5:A*/ /[B6:A]/ /<B7>/ /<B8:long>/; B : S ::= B1:A B2:A* [B3:A] /B4:A/ /B5:A*/ /[B6:A]/ /<B7>/ /<B8:long>/;
X; X;
Y; Y;
C : B ::= /<B8:long>/ /<B7>/ /[B6:A]/ /B5:A*/ /B4:A/ [B3:A] B2:A* B1:A;
rel A.r1 -> X; rel A.r1 -> X;
rel S.r2* <-> Y.r2; rel S.r2* <-> Y.r2;
......
...@@ -63,3 +63,5 @@ G : C ::= [D] ; ...@@ -63,3 +63,5 @@ G : C ::= [D] ;
// line comment with special symbols like |, *, ->, <-, <->, [A], B ::= C, :, \n, \r, ~, #, /A/ // line comment with special symbols like |, *, ->, <-, <->, [A], B ::= C, :, \n, \r, ~, #, /A/
/* block comment with special symbols like |, *, ->, <-, <->, [A], B ::= C, :, \n, \r, ~, #, /A/ */ /* block comment with special symbols like |, *, ->, <-, <->, [A], B ::= C, :, \n, \r, ~, #, /A/ */
abstract Uninstantiable:A;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment