Fix YANG snippet escaping 38/88338/2
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 2 Mar 2020 12:58:50 +0000 (13:58 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 6 Mar 2020 19:44:27 +0000 (20:44 +0100)
This is the non-javadoc path for module generation, where we are
failing to escape potential unicode references. Add the proper
callout and also optimize it to be a faster no-op when not
applicable, properly documenting what is going on.

JIRA: MDSAL-529
Change-Id: Ib21ed4f15555d49aaa7eb3dac61043c4b2e90451
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/BindingGeneratorUtil.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CompilationTest.java
binding/mdsal-binding-java-api-generator/src/test/resources/compilation/mdsal529/foo.yang [new file with mode: 0644]

index 563e58e36022d98990d07d5aa42da3c23f3aae32..15b733a06345f50f5b8e340bca9b4bd10a66b98b 100644 (file)
@@ -410,7 +410,28 @@ public final class BindingGeneratorUtil {
         return description;
     }
 
+    @Deprecated
     public static String replaceAllIllegalChars(final CharSequence stringBuilder) {
+        return defangUnicodeEscapes(stringBuilder);
+    }
+
+    /**
+     * Escape potential unicode references so that the resulting string is safe to put into a {@code .java} file. This
+     * processing is required to ensure this text we want to append does not end up with eligible backslashes. See
+     * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.3">Java Language Specification</a>
+     * for more information.
+     *
+     * @param str Input string
+     * @return A string with all backslashes made ineligible
+     */
+    public static String replaceAllIllegalChars(final String str) {
+        final int backslash = str.indexOf('\\');
+        return backslash == -1 ? str : defangUnicodeEscapes(str);
+    }
+
+    private static String defangUnicodeEscapes(final CharSequence stringBuilder) {
+        // TODO: we should be able to receive the first offset from the non-deprecated method and perform a manual
+        //       check for eligibility and escape -- that would be faster I think.
         final String ret = UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");
         return ret.isEmpty() ? "" : ret;
     }
index 6b2bd491465d586af5a59a6923e07f99c72ef500..71005ca2ac6b1c9fb8b45c0911573bb7328251b5 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.mdsal.binding.model.api.Type
 import org.opendaylight.mdsal.binding.model.api.TypeMember
 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Single
 import org.opendaylight.mdsal.binding.model.api.YangSourceDefinition.Multiple
+import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil
 import org.opendaylight.mdsal.binding.model.util.TypeConstants
 import org.opendaylight.mdsal.binding.model.util.Types
 import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
@@ -285,7 +286,7 @@ abstract class BaseTemplate extends JavaFileTemplate {
     def private static void appendYangSnippet(StringBuilder sb, ModuleEffectiveStatement module,
             DeclaredStatement<?> stmt) {
         for (String str : YANG_FORMATTER.toYangTextSnippet(module, stmt)) {
-            sb.append(encodeAngleBrackets(encodeJavadocSymbols(str)))
+            sb.append(BindingGeneratorUtil.replaceAllIllegalChars(encodeAngleBrackets(encodeJavadocSymbols(str))))
         }
     }
 
index a62dc5ad4dce0fc78f8540510e90a5dc766ed61c..16aa921b6da77484bcb042c0050f9fc3d85bbfb0 100644 (file)
@@ -681,6 +681,15 @@ public class CompilationTest extends BaseCompilationTest {
         CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir);
     }
 
+    @Test
+    public void testMdsal529() throws Exception {
+        final File sourcesOutputDir = CompilationTestUtils.generatorOutput("mdsal529");
+        final File compiledOutputDir = CompilationTestUtils.compilerOutput("mdsal529");
+        generateTestSources("/compilation/mdsal529", sourcesOutputDir);
+        CompilationTestUtils.testCompilation(sourcesOutputDir, compiledOutputDir);
+        CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
     private static void testReturnTypeIdentityref(final Class<?> clazz, final String methodName,
             final String returnTypeStr) throws NoSuchMethodException {
         Method method = clazz.getMethod(methodName);
diff --git a/binding/mdsal-binding-java-api-generator/src/test/resources/compilation/mdsal529/foo.yang b/binding/mdsal-binding-java-api-generator/src/test/resources/compilation/mdsal529/foo.yang
new file mode 100644 (file)
index 0000000..e6cbfbf
--- /dev/null
@@ -0,0 +1,25 @@
+module foo {
+  namespace foo;
+  prefix foo;
+
+  leaf foo {
+    type string;
+    default "\\u@\\h\\M% ";
+  }
+
+  leaf bar {
+    type string;
+    default "\\uu";
+  }
+
+  leaf baz {
+    type string;
+    default "\\a\\uu";
+  }
+
+  leaf xyzzy {
+    type string;
+    default '\uuuaaa';
+  }
+}
+