Skip to content

Commit a0d8b86

Browse files
mbeckerleolabusayoT
authored andcommitted
Create version specific folders for macros
- update scalafmt to use the scala 2.13 dialect unless it's in a scala-3 directory or is an sbt file - create version specific directories for Macros and the objects that use them, with the traits/functions that need macros defined within the *UsingMacrosMixin traits. The only exception is needing to define AssertMacros outside of macro-lib since it needs access to the Assert class at compilation time and the macro class doesn't depend on the lib module. - fix issue with abstract lazy val in NodeInfo, by removing it since it's not needed - fix test path scala version for scala 3. Since Scala 3 uses the 2.13.16 library, scala.util.Properties.versionNumberString returns the library version, which in Scala 3 is 2.13.16. So we use universal/stage/lib to get the scala library version - set type as needed - verify removal of protected defs needed in scala 3 - fix formatting issue with frames map - replace equals override with matches def since scla 3 doesn't allow comparing a string and DebugCommand using == - make scalaVersionForTargetPath lazy DAFFODIL-2975
1 parent 4ae3eda commit a0d8b86

File tree

44 files changed

+907
-244
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+907
-244
lines changed

.scalafmt.conf

+9-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ rewrite.rules = [
3030
Imports,
3131
]
3232
rewrite.trailingCommas.style = never
33-
runner.dialect = scala212
33+
runner.dialect = scala213
3434
spaces.inImportCurlyBraces = true
3535
version = 3.8.3
36+
fileOverride {
37+
"glob:**/src/main/scala-3/**" {
38+
runner.dialect = scala3
39+
}
40+
"glob:**.sbt" {
41+
runner.dialect = scala3
42+
}
43+
}

daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest/Util.scala

+29-4
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,35 @@ object Util {
5757
Paths.get(s"daffodil-cli/target/universal/stage/bin/daffodil$ext")
5858
}
5959

60-
val scalaVersionForTargetPath: String = scala.util.Properties.versionNumberString match {
61-
case v if v.startsWith("2.12") => "scala-2.12"
62-
case v if v.startsWith("2.13") => "scala-2.13"
63-
case _ => throw new IllegalStateException("Unsupported version provided for tests")
60+
lazy val scalaVersionForTargetPath: String = {
61+
// scala.util.Properties.versionNumberString doesn't actually return scala 3.3.5 as expected
62+
// when called in scala 3, as it returns the library version which is 2.13.16 for scala 2 and scala 3
63+
// so we try to get the scala 3 version from the jar files and if it fails, we try for the scala 2 library
64+
val scala3Regex = "org\\.scala-lang\\.scala3-library_3-([0-9.]+)\\.jar".r
65+
val scala2Regex = "org\\.scala-lang\\.scala-library-([0-9.]+)\\.jar".r
66+
val versionRegex = ".*-([0-9.]+)\\.jar".r
67+
68+
val jarFiles = Paths.get("daffodil-cli/target/universal/stage/lib").toFile.listFiles().toSeq
69+
70+
// Prioritize finding Scala 3 first, then fallback to Scala 2
71+
val scalaLibraryFile = jarFiles
72+
.find(f => scala3Regex.pattern.matcher(f.getName).matches())
73+
.orElse(jarFiles.find(f => scala2Regex.pattern.matcher(f.getName).matches()))
74+
.getOrElse(throw new IllegalStateException("No Scala library JAR found"))
75+
76+
// Extract Scala version using regex
77+
val scalaVersion = versionRegex
78+
.findFirstMatchIn(scalaLibraryFile.getName)
79+
.map(_.group(1))
80+
.getOrElse(throw new IllegalStateException("No Scala Version found"))
81+
82+
scalaVersion match {
83+
case v if v.startsWith("2.12") => "scala-2.12"
84+
case v if v.startsWith("2.13") => "scala-2.13"
85+
case v if v.startsWith("3.") => "scala-" + v
86+
case _ =>
87+
throw new IllegalStateException(s"Unsupported version $scalaVersion provided for tests")
88+
}
6489
}
6590

6691
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.daffodil.io
19+
20+
trait IOUsingMacrosMixin {
21+
22+
/**
23+
* Convenience methods that temporarily set and (reliably) restore the bitLimit.
24+
* The argument gives the limit length. Note this is a length, not a bit position.
25+
*
26+
* This is added to the current bit position to get the limiting bit position
27+
* which is then set as the bitLimit when
28+
* the body is evaluated. On return the bit limit is restored to its
29+
* prior value.
30+
* <p>
31+
* The return value is false if the new bit limit is beyond the existing bit limit range.
32+
* Otherwise the return value is true.
33+
* <p>
34+
* The prior value is restored even if an Error/Exception is thrown. (ie., via a try-finally)
35+
* <p>
36+
* These are intended for use implementing specified-length types (simple or complex).
37+
* <p>
38+
* Note that length limits in lengthUnits Characters are not implemented
39+
* this way. See fillCharBuffer(cb) method.
40+
*/
41+
final def withBitLengthLimit(lengthLimitInBits: Long)(body: => Unit): Boolean =
42+
macro IOMacros.withBitLengthLimitMacroForInput
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.daffodil.io
19+
20+
trait IOUsingMacrosMixin {
21+
this: org.apache.daffodil.io.DataInputStream =>
22+
23+
/**
24+
* Convenience methods that temporarily set and (reliably) restore the bitLimit.
25+
* The argument gives the limit length. Note this is a length, not a bit position.
26+
*
27+
* This is added to the current bit position to get the limiting bit position
28+
* which is then set as the bitLimit when
29+
* the body is evaluated. On return the bit limit is restored to its
30+
* prior value.
31+
* <p>
32+
* The return value is false if the new bit limit is beyond the existing bit limit range.
33+
* Otherwise the return value is true.
34+
* <p>
35+
* The prior value is restored even if an Error/Exception is thrown. (ie., via a try-finally)
36+
* <p>
37+
* These are intended for use implementing specified-length types (simple or complex).
38+
* <p>
39+
* Note that length limits in lengthUnits Characters are not implemented
40+
* this way. See fillCharBuffer(cb) method.
41+
*/
42+
final inline def withBitLengthLimit(
43+
lengthLimitInBits: Long
44+
)(inline body: => Unit): Boolean = {
45+
import org.apache.daffodil.lib.util.MaybeULong
46+
47+
val dStream = this
48+
val newLengthLimit = lengthLimitInBits
49+
val savedLengthLimit = dStream.bitLimit0b
50+
51+
if (!dStream.setBitLimit0b(MaybeULong(dStream.bitPos0b + newLengthLimit))) false
52+
else {
53+
try {
54+
body
55+
} finally {
56+
dStream.resetBitLimit0b(savedLengthLimit)
57+
}
58+
true
59+
}
60+
}
61+
}

daffodil-io/src/main/scala/org/apache/daffodil/io/DataInputStream.scala

+1-24
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
1817
package org.apache.daffodil.io
1918

2019
import java.math.{ BigInteger => JBigInt }
@@ -169,7 +168,7 @@ object DataInputStream {
169168

170169
}
171170

172-
trait DataInputStream extends DataStreamCommon {
171+
trait DataInputStream extends DataStreamCommon with IOUsingMacrosMixin {
173172
import DataInputStream._
174173

175174
/**
@@ -529,28 +528,6 @@ trait DataInputStream extends DataStreamCommon {
529528
def markPos: MarkPos
530529
def resetPos(m: MarkPos): Unit
531530

532-
/**
533-
* Convenience methods that temporarily set and (reliably) restore the bitLimit.
534-
* The argument gives the limit length. Note this is a length, not a bit position.
535-
*
536-
* This is added to the current bit position to get the limiting bit position
537-
* which is then set as the bitLimit when
538-
* the body is evaluated. On return the bit limit is restored to its
539-
* prior value.
540-
* <p>
541-
* The return value is false if the new bit limit is beyond the existing bit limit range.
542-
* Otherwise the return value is true.
543-
* <p>
544-
* The prior value is restored even if an Error/Exception is thrown. (ie., via a try-finally)
545-
* <p>
546-
* These are intended for use implementing specified-length types (simple or complex).
547-
* <p>
548-
* Note that length limits in lengthUnits Characters are not implemented
549-
* this way. See fillCharBuffer(cb) method.
550-
*/
551-
final def withBitLengthLimit(lengthLimitInBits: Long)(body: => Unit): Boolean =
552-
macro IOMacros.withBitLengthLimitMacroForInput
553-
554531
/**
555532
* Closes any underlying I/O streams/channels that are part of the implementation
556533
* of this and frees related resources.

daffodil-io/src/main/scala/org/apache/daffodil/io/DataOutputStreamImplMixin.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ trait DataOutputStreamImplMixin
277277
* Returns false if the set was unsuccessful, meaning one is setting a limit that
278278
* extends past a pre-existing limit.
279279
*/
280-
protected def setMaybeRelBitLimit0b(
280+
def setMaybeRelBitLimit0b(
281281
newMaybeRelBitLimit0b: MaybeULong,
282282
reset: Boolean = false
283283
): Boolean = {
@@ -330,7 +330,7 @@ trait DataOutputStreamImplMixin
330330
* Always between 0 and 7 inclusive.
331331
*/
332332
private var fragmentLastByteLimit_ : Int = 0
333-
def fragmentLastByteLimit = fragmentLastByteLimit_
333+
def fragmentLastByteLimit: Int = fragmentLastByteLimit_
334334

335335
def setFragmentLastByte(newFragmentByte: Int, nBitsInUse: Int): Unit = {
336336
Assert.usage(nBitsInUse >= 0 && nBitsInUse <= 7)
@@ -375,7 +375,7 @@ trait DataOutputStreamImplMixin
375375

376376
protected def getJavaOutputStream(): java.io.OutputStream
377377

378-
final protected def cst = this
378+
final def cst: DataOutputStreamImplMixin = this
379379

380380
protected def assignFrom(other: DataOutputStreamImplMixin): Unit = {
381381
Assert.usage(isWritable)
@@ -711,7 +711,7 @@ trait DataOutputStreamImplMixin
711711
): Long = {
712712
Assert.usage(isWritable)
713713
if (isEndOnByteBoundary) {
714-
val nBytes =
714+
val nBytes: Long =
715715
if (exceedsBitLimit(lengthInBytes)) {
716716
val n = (maybeRelBitLimit0b.getULong - relBitPos0b) / 8
717717
Assert.invariant(n >= 0)
@@ -849,7 +849,7 @@ trait DataOutputStreamImplMixin
849849

850850
private def putByteBuffer(bb: java.nio.ByteBuffer, finfo: FormatInfo): Long = {
851851
Assert.usage(isWritable)
852-
val nTransferred =
852+
val nTransferred: Long =
853853
if (bb.hasArray) {
854854
putBytes(bb.array, bb.arrayOffset + bb.position(), bb.remaining(), finfo)
855855
} else {

daffodil-io/src/main/scala/org/apache/daffodil/io/Dump.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -617,14 +617,14 @@ class DataDumper {
617617
Assert.invariant(cb.hasArray)
618618
val allChars = cb.array
619619

620-
val uCodePoint =
620+
val uCodePoint: Int =
621621
if (allChars.length > 1) {
622622
if (UCharacter.isSurrogatePair(allChars(0), allChars(1))) {
623623
UCharacter.getCodePoint(allChars(0), allChars(1))
624624
} else {
625625
INVALID_CODEPOINT
626626
}
627-
} else allChars(0)
627+
} else allChars(0).toInt
628628

629629
val (r: String, n: Int) =
630630
if (allChars.length > 1) {

daffodil-io/src/main/scala/org/apache/daffodil/io/processors/charset/BitsCharsetDefinition.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ abstract class BitsCharsetDefinition(
3030
) extends SimpleNamedLoadableService {
3131
final def name(): String = alias.getOrElse(charsetArg.name).toUpperCase()
3232

33-
final def charset(): BitsCharset = charsetArg
33+
final def charset: BitsCharset = charsetArg
3434
}

daffodil-io/src/main/scala/org/apache/daffodil/io/processors/charset/CharsetUtils.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ object CharsetUtils {
3838
if (cs == null)
3939
null
4040
else
41-
cs.charset()
41+
cs.charset
4242
}
4343

4444
def supportedEncodingsString = BitsCharsetDefinitionRegistry.supportedEncodingsString

daffodil-japi/src/test/java/org/apache/daffodil/example/TestCustomDebuggerAPI.java

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import java.io.IOException;
3333
import java.net.URI;
3434

35-
import static java.util.Objects.nonNull;
3635
import static org.junit.Assert.assertEquals;
3736
import static org.junit.Assert.assertTrue;
3837

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.daffodil.lib.exceptions
19+
20+
trait AssertsUsingMacrosMixin {
21+
22+
/**
23+
* Verbose name helps you get the sense of the predicate right.
24+
*/
25+
def usageErrorUnless(testAbortsIfFalse: Boolean, message: String): Unit =
26+
macro AssertMacros.usageMacro2
27+
28+
def usageErrorUnless(testAbortsIfFalse: Boolean, cause: Throwable): Unit =
29+
macro AssertMacros.usageMacro2Cause
30+
31+
def usageErrorUnless(testAbortsIfFalse: Boolean): Unit = macro AssertMacros.usageMacro1
32+
33+
/**
34+
* Brief form
35+
*/
36+
def usage(testAbortsIfFalse: Boolean, message: String): Unit = macro AssertMacros.usageMacro2
37+
38+
def usageWithCause(testAbortsIfFalse: Boolean, cause: Throwable): Unit =
39+
macro AssertMacros.usageMacro2Cause
40+
41+
def usage(testAbortsIfFalse: Boolean): Unit =
42+
macro AssertMacros.usageMacro1
43+
44+
/**
45+
* test for something that the program is supposed to be ensuring.
46+
*
47+
* This is for more complex invariants than the simple 'impossible' case.
48+
*/
49+
def invariant(testAbortsIfFalse: Boolean): Unit = macro AssertMacros.invariantMacro1
50+
51+
/**
52+
* test for something that the program is supposed to be ensuring, with a custom error message.
53+
*
54+
* This is for more complex invariants than the simple 'impossible' case.
55+
*
56+
* The msg parameter is only evaluated if the test fails
57+
*/
58+
def invariant(testAbortsIfFalse: Boolean, msg: String): Unit =
59+
macro AssertMacros.invariantMacro2
60+
61+
/**
62+
* Conditional behavior for NYIs
63+
*/
64+
def notYetImplemented(testThatWillThrowIfTrue: Boolean): Unit =
65+
macro AssertMacros.notYetImplementedMacro1
66+
67+
def notYetImplemented(testThatWillThrowIfTrue: Boolean, msg: String): Unit =
68+
macro AssertMacros.notYetImplementedMacro2
69+
}

0 commit comments

Comments
 (0)