From 8c44333652dfba01f9f76ceac773d6c18ea57e9d Mon Sep 17 00:00:00 2001
From: Gerwin Klein <lsf@jflex.de>
Date: Fri, 6 Jan 2023 16:58:25 +1100
Subject: [PATCH 1/6] jflex AbstractLexScan: remove TODO

Char classes still need to be mutable at this point. They can only be
made immutable after the semantic analysis phase at the end of parsing.
---
 jflex/src/main/java/jflex/core/AbstractLexScan.java | 1 -
 1 file changed, 1 deletion(-)

diff --git a/jflex/src/main/java/jflex/core/AbstractLexScan.java b/jflex/src/main/java/jflex/core/AbstractLexScan.java
index 4e38a0c2e..e808c26db 100644
--- a/jflex/src/main/java/jflex/core/AbstractLexScan.java
+++ b/jflex/src/main/java/jflex/core/AbstractLexScan.java
@@ -89,7 +89,6 @@ public UnicodeProperties getUnicodeProperties() {
     return unicodeProperties;
   }
 
-  // TODO(regisd) Return an immutable representation of char classes
   @SuppressWarnings("unused") // Used in generated LexParse
   public CharClasses getCharClasses() {
     return charClasses;

From f44691e136bf3e8b5b93f6218b6e28d9fffcaa68 Mon Sep 17 00:00:00 2001
From: Gerwin Klein <lsf@jflex.de>
Date: Fri, 6 Jan 2023 17:07:34 +1100
Subject: [PATCH 2/6] jflex: add %no_suppress_warnings directive

By default JFlex emits @SuppressWarnings("fallthrough") at the class
level. This directive removes that annotation and leaves it up to the
user to define their own.

Fixes #762
---
 jflex/src/main/java/jflex/core/AbstractLexScan.java | 5 +++++
 jflex/src/main/java/jflex/generator/Emitter.java    | 7 ++++---
 jflex/src/main/jflex/LexScan.flex                   | 2 ++
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/jflex/src/main/java/jflex/core/AbstractLexScan.java b/jflex/src/main/java/jflex/core/AbstractLexScan.java
index e808c26db..1e67f80ef 100644
--- a/jflex/src/main/java/jflex/core/AbstractLexScan.java
+++ b/jflex/src/main/java/jflex/core/AbstractLexScan.java
@@ -67,6 +67,7 @@ public enum CharSetSize {
   boolean standalone;
   boolean debugOption;
   boolean eofclose;
+  boolean noSuppressWarnings;
 
   String isImplementing;
   String isExtending;
@@ -395,6 +396,10 @@ public int bufferSize() {
     return bufferSize;
   }
 
+  public boolean noSuppressWarnings() {
+    return noSuppressWarnings;
+  }
+
   /**
    * Returns the current line number.
    *
diff --git a/jflex/src/main/java/jflex/generator/Emitter.java b/jflex/src/main/java/jflex/generator/Emitter.java
index 97bad86b4..748a539bc 100644
--- a/jflex/src/main/java/jflex/generator/Emitter.java
+++ b/jflex/src/main/java/jflex/generator/Emitter.java
@@ -429,9 +429,10 @@ private void emitUserCode() {
   }
 
   private void emitClassName() {
-    // TODO(#222) Actually fix the fall-through violations
-    println("// See https://github.com/jflex-de/jflex/issues/222");
-    println("@SuppressWarnings(\"FallThrough\")");
+    if (!scanner.noSuppressWarnings()) {
+      // TODO(#222) Actually fix the fall-through violations
+      println("@SuppressWarnings(\"fallthrough\")");
+    }
     if (scanner.isPublic()) print("public ");
 
     if (scanner.isAbstract()) print("abstract ");
diff --git a/jflex/src/main/jflex/LexScan.flex b/jflex/src/main/jflex/LexScan.flex
index 99675eba2..66837d976 100644
--- a/jflex/src/main/jflex/LexScan.flex
+++ b/jflex/src/main/jflex/LexScan.flex
@@ -281,6 +281,8 @@ DottedVersion =  [1-9][0-9]*(\.[0-9]+){0,2}
   "%warn" {WSP}+ {WarningIdent} {WSP}* { OptionUtils.enableWarning(yytext().substring(6).trim()); }
   "%warn" {WSP}+ {NNL}* { throw new ScannerException(file, ErrorMessages.NOT_A_WARNING_ID, yyline); }
 
+  "%no_suppress_warnings" {WSP}* { noSuppressWarnings = true; }
+
   {Ident}                     { return symbol(IDENT, yytext()); }
   "="{WSP}*                   { yybegin(REGEXP);
                                 return symbol(EQUALS);

From c6a9a3e57d8bd1879f3d067ab40b7f160e534fec Mon Sep 17 00:00:00 2001
From: Gerwin Klein <lsf@jflex.de>
Date: Fri, 6 Jan 2023 17:11:58 +1100
Subject: [PATCH 3/6] docs: document %no_suppress_warnings

---
 docs/md/lex-specs.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/docs/md/lex-specs.md b/docs/md/lex-specs.md
index b44a6869b..cf0250023 100644
--- a/docs/md/lex-specs.md
+++ b/docs/md/lex-specs.md
@@ -86,6 +86,12 @@ generated scanner class.
 
     Makes the generated class abstract.
 
+-   `%no_suppress_warnings`
+
+    Do not generate any `@SuppressWarnings(...)` annotation for the generated
+    class. This means, you can add your own `@SuppressWarnings(...)` annotation
+    in the preamble without getting a compiler error on duplicate annotations.
+
 -   `%apiprivate`
 
     Makes all generated methods and fields of the class private.

From afb5a920e3049ff0c31b7a5a7cf6df2192fb73ae Mon Sep 17 00:00:00 2001
From: Gerwin Klein <lsf@jflex.de>
Date: Fri, 6 Jan 2023 17:28:17 +1100
Subject: [PATCH 4/6] test: add test for %no_suppress_warnings

---
 .../testcase/no_suppress_warnings/BUILD.bazel | 18 +++++++++++++++++
 .../no_suppress_warnings/NoSuppressTest.java  | 20 +++++++++++++++++++
 .../no_suppress_warnings/expected_sysout.txt  |  0
 .../no_suppress_warnings/no_suppress.flex     | 20 +++++++++++++++++++
 4 files changed, 58 insertions(+)
 create mode 100644 javatests/de/jflex/testcase/no_suppress_warnings/BUILD.bazel
 create mode 100644 javatests/de/jflex/testcase/no_suppress_warnings/NoSuppressTest.java
 create mode 100644 javatests/de/jflex/testcase/no_suppress_warnings/expected_sysout.txt
 create mode 100644 javatests/de/jflex/testcase/no_suppress_warnings/no_suppress.flex

diff --git a/javatests/de/jflex/testcase/no_suppress_warnings/BUILD.bazel b/javatests/de/jflex/testcase/no_suppress_warnings/BUILD.bazel
new file mode 100644
index 000000000..8a1d0caa7
--- /dev/null
+++ b/javatests/de/jflex/testcase/no_suppress_warnings/BUILD.bazel
@@ -0,0 +1,18 @@
+# Copyright 2023, Gerwin Klein
+# SPDX-License-Identifier: BSD-3-Clause
+
+load("//testsuite:testsuite.bzl", "jflex_testsuite")
+
+jflex_testsuite(
+    name = "NoSuppressTest",
+    srcs = [
+        "NoSuppressTest.java",
+    ],
+    data = [
+        "expected_sysout.txt",
+        "no_suppress.flex",
+    ],
+    deps = [
+        "//third_party/com/google/guava",
+    ],
+)
diff --git a/javatests/de/jflex/testcase/no_suppress_warnings/NoSuppressTest.java b/javatests/de/jflex/testcase/no_suppress_warnings/NoSuppressTest.java
new file mode 100644
index 000000000..98c5c52f1
--- /dev/null
+++ b/javatests/de/jflex/testcase/no_suppress_warnings/NoSuppressTest.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2023, Gerwin Klein.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package de.jflex.testcase.no_suppress_warnings;
+
+import de.jflex.testing.testsuite.JFlexTestRunner;
+import de.jflex.testing.testsuite.annotations.TestSpec;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Test nevermatch warning. */
+@RunWith(JFlexTestRunner.class)
+@TestSpec(lex = "javatests/de/jflex/testcase/no_suppress_warnings/no_suppress.flex", quiet = true)
+public class NoSuppressTest {
+
+  /** Tests that the scanner was successfully generated and can be instantiated. */
+  @Test
+  public void ok() throws Exception {}
+}
diff --git a/javatests/de/jflex/testcase/no_suppress_warnings/expected_sysout.txt b/javatests/de/jflex/testcase/no_suppress_warnings/expected_sysout.txt
new file mode 100644
index 000000000..e69de29bb
diff --git a/javatests/de/jflex/testcase/no_suppress_warnings/no_suppress.flex b/javatests/de/jflex/testcase/no_suppress_warnings/no_suppress.flex
new file mode 100644
index 000000000..02f2754ec
--- /dev/null
+++ b/javatests/de/jflex/testcase/no_suppress_warnings/no_suppress.flex
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2023, Gerwin Klein <lsf@jflex.de>
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package de.jflex.testcase.no_suppress_warnings;
+
+// will lead to compile error if JFlex emits its own @SuppressWarnings
+@SuppressWarnings("all")
+%%
+
+%no_suppress_warnings
+%class NoSuppress
+%debug
+%int
+
+%%
+
+a|b  { return 1; }
+[^]  { return 0; }
\ No newline at end of file

From 6c03a668f674cfe3f355a5d3677445738e3f71ca Mon Sep 17 00:00:00 2001
From: Gerwin Klein <lsf@jflex.de>
Date: Fri, 6 Jan 2023 17:35:03 +1100
Subject: [PATCH 5/6] tests: enable missed tests

Looks like BUILD.bzl wasn't picked up; renamed to BUILD.bazel and fixed
output drift.
---
 .../de/jflex/testcase/negation/{BUILD.bzl => BUILD.bazel}     | 0
 javatests/de/jflex/testcase/negation/negation-0.output        | 2 +-
 javatests/de/jflex/testcase/negation/negation-1.output        | 2 +-
 .../de/jflex/testcase/nevermatch/{BUILD.bzl => BUILD.bazel}   | 0
 javatests/de/jflex/testcase/nevermatch/expected_sysout.txt    | 4 ++--
 .../de/jflex/testcase/semcheck/{BUILD.bzl => BUILD.bazel}     | 0
 javatests/de/jflex/testcase/semcheck/semcheck-flex.output     | 2 +-
 .../jflex/testcase/unused_warning/{BUILD.bzl => BUILD.bazel}  | 0
 .../jflex/testcase/unused_warning/expected_unused_sysout.txt  | 2 +-
 9 files changed, 6 insertions(+), 6 deletions(-)
 rename javatests/de/jflex/testcase/negation/{BUILD.bzl => BUILD.bazel} (100%)
 rename javatests/de/jflex/testcase/nevermatch/{BUILD.bzl => BUILD.bazel} (100%)
 rename javatests/de/jflex/testcase/semcheck/{BUILD.bzl => BUILD.bazel} (100%)
 rename javatests/de/jflex/testcase/unused_warning/{BUILD.bzl => BUILD.bazel} (100%)

diff --git a/javatests/de/jflex/testcase/negation/BUILD.bzl b/javatests/de/jflex/testcase/negation/BUILD.bazel
similarity index 100%
rename from javatests/de/jflex/testcase/negation/BUILD.bzl
rename to javatests/de/jflex/testcase/negation/BUILD.bazel
diff --git a/javatests/de/jflex/testcase/negation/negation-0.output b/javatests/de/jflex/testcase/negation/negation-0.output
index 4dbd6793e..2ab616e14 100644
--- a/javatests/de/jflex/testcase/negation/negation-0.output
+++ b/javatests/de/jflex/testcase/negation/negation-0.output
@@ -1,3 +1,3 @@
 line: 1 col: 1 match: --aba\u000A--
-action [17] { /* all */ }
+action [22] { /* all */ }
 -1
diff --git a/javatests/de/jflex/testcase/negation/negation-1.output b/javatests/de/jflex/testcase/negation/negation-1.output
index 82f110ebe..45e31d29b 100644
--- a/javatests/de/jflex/testcase/negation/negation-1.output
+++ b/javatests/de/jflex/testcase/negation/negation-1.output
@@ -1,3 +1,3 @@
 line: 1 col: 1 match: --baba--
-action [17] { /* all */ }
+action [22] { /* all */ }
 -1
diff --git a/javatests/de/jflex/testcase/nevermatch/BUILD.bzl b/javatests/de/jflex/testcase/nevermatch/BUILD.bazel
similarity index 100%
rename from javatests/de/jflex/testcase/nevermatch/BUILD.bzl
rename to javatests/de/jflex/testcase/nevermatch/BUILD.bazel
diff --git a/javatests/de/jflex/testcase/nevermatch/expected_sysout.txt b/javatests/de/jflex/testcase/nevermatch/expected_sysout.txt
index cd13adad0..691c06dec 100644
--- a/javatests/de/jflex/testcase/nevermatch/expected_sysout.txt
+++ b/javatests/de/jflex/testcase/nevermatch/expected_sysout.txt
@@ -3,11 +3,11 @@ Constructing NFA : 12 states in NFA
 Converting NFA to DFA : 
 .....
 
-Warning in file "javatests/de/jflex/testcase/nevermatch/never.flex" (line 15): 
+Warning in file "javatests/de/jflex/testcase/nevermatch/never.flex" (line 20): 
 Rule can never be matched:
 <A> .    { /* action */ }
 
-Warning in file "javatests/de/jflex/testcase/nevermatch/never.flex" (line 21): 
+Warning in file "javatests/de/jflex/testcase/nevermatch/never.flex" (line 26): 
 Rule can never be matched:
 <A> <<EOF>>  { /* action 4 */ }
 11 states before minimization, 4 states in minimized DFA
diff --git a/javatests/de/jflex/testcase/semcheck/BUILD.bzl b/javatests/de/jflex/testcase/semcheck/BUILD.bazel
similarity index 100%
rename from javatests/de/jflex/testcase/semcheck/BUILD.bzl
rename to javatests/de/jflex/testcase/semcheck/BUILD.bazel
diff --git a/javatests/de/jflex/testcase/semcheck/semcheck-flex.output b/javatests/de/jflex/testcase/semcheck/semcheck-flex.output
index 04f43e89e..2e51b8475 100644
--- a/javatests/de/jflex/testcase/semcheck/semcheck-flex.output
+++ b/javatests/de/jflex/testcase/semcheck/semcheck-flex.output
@@ -1,5 +1,5 @@
 Reading "javatests/de/jflex/testcase/semcheck/semcheck.flex"
 
-Error in file "javatests/de/jflex/testcase/semcheck/semcheck.flex" (line 12): 
+Error in file "javatests/de/jflex/testcase/semcheck/semcheck.flex" (line 17): 
 Lookahead expression must have match with length of at least 1.
 !"foo" / "bar"  {  }
diff --git a/javatests/de/jflex/testcase/unused_warning/BUILD.bzl b/javatests/de/jflex/testcase/unused_warning/BUILD.bazel
similarity index 100%
rename from javatests/de/jflex/testcase/unused_warning/BUILD.bzl
rename to javatests/de/jflex/testcase/unused_warning/BUILD.bazel
diff --git a/javatests/de/jflex/testcase/unused_warning/expected_unused_sysout.txt b/javatests/de/jflex/testcase/unused_warning/expected_unused_sysout.txt
index 3a6ca4f36..459e3515b 100644
--- a/javatests/de/jflex/testcase/unused_warning/expected_unused_sysout.txt
+++ b/javatests/de/jflex/testcase/unused_warning/expected_unused_sysout.txt
@@ -1,6 +1,6 @@
 Reading "javatests/de/jflex/testcase/unused_warning/unused.flex"
 
-Warning : Macro "UNUSED" has been declared but never used.
+Warning: Macro "UNUSED" has been declared but never used.
 Constructing NFA : 4 states in NFA
 Converting NFA to DFA : 
 .

From e2f5d007235c6c36425f163aa6bf1dcd2624f891 Mon Sep 17 00:00:00 2001
From: Gerwin Klein <lsf@jflex.de>
Date: Fri, 6 Jan 2023 20:22:39 +1100
Subject: [PATCH 6/6] github: suppress more codeql warnings

- LexScan.java: uncaught-number-format-exception:
  Format is checked by the lexer spec.

- LexScan.java: misleading-indentation: in comment only.
---
 .github/workflows/codeql.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index cee0b02b0..887fbebca 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -50,6 +50,8 @@ jobs:
         with:
           patterns: |
             -**/LexParse.java:java/local-variable-is-never-read
+            -**/LexScan.java:java/misleading-indentation
+            -**/LexScan.java:java/uncaught-number-format-exception
           input: sarif-results/java.sarif
           output: sarif-results/java.sarif