From ca502625eed5a75063b00ee18cdf049fd1fe60da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Guillemet?= Date: Mon, 29 Jan 2024 11:25:21 +0100 Subject: [PATCH 1/2] Check for name duplicates in containers --- .../org/bytedeco/javacpp/tools/Parser.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/bytedeco/javacpp/tools/Parser.java b/src/main/java/org/bytedeco/javacpp/tools/Parser.java index 04a5ff7b..c431d026 100644 --- a/src/main/java/org/bytedeco/javacpp/tools/Parser.java +++ b/src/main/java/org/bytedeco/javacpp/tools/Parser.java @@ -181,6 +181,12 @@ String translate(String text) { return text; } + /** De-deduplicate an array of strings, keeping order. */ + private static String[] uniq(String[] a) { + if (a == null || a.length <= 1) return a; + return new LinkedHashSet<>(Arrays.asList(a)).toArray(new String[0]); + } + void containers(Context context, DeclarationList declList) throws ParserException { List basicContainers = new ArrayList<>(); for (Info info : infoMap.get("basic/containers")) { @@ -339,8 +345,8 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio + " public " + containerType.javaName + "(Pointer p) { super(p); }\n"; boolean purify = info != null && info.purify; if (!constant && !purify && (dim == 0 || (containerType.arguments.length == 1 && indexType != null)) && firstType != null && secondType != null) { - String[] firstNames = firstType.javaNames != null ? firstType.javaNames : new String[] {firstType.javaName}; - String[] secondNames = secondType.javaNames != null ? secondType.javaNames : new String[] {secondType.javaName}; + String[] firstNames = firstType.javaNames != null ? uniq(firstType.javaNames) : new String[] {firstType.javaName}; + String[] secondNames = secondType.javaNames != null ? uniq(secondType.javaNames) : new String[] {secondType.javaName}; String brackets = arrayBrackets + (dim > 0 ? "[]" : ""); for (int n = 0; n < firstNames.length || n < secondNames.length; n++) { decl.text += " public " + containerType.javaName + "(" + firstNames[Math.min(n, firstNames.length - 1)] + brackets + " firstValue, " @@ -348,7 +354,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio + "{ this(" + (dim > 0 ? "Math.min(firstValue.length, secondValue.length)" : "") + "); put(firstValue, secondValue); }\n"; } } else if (resizable && !purify && firstType == null && secondType == null) { - for (String javaName : valueType.javaNames != null ? valueType.javaNames : new String[] {valueType.javaName}) { + for (String javaName : valueType.javaNames != null ? uniq(valueType.javaNames) : new String[] {valueType.javaName}) { if (dim < 2 && !javaName.equals("int") && !javaName.equals("long")) { decl.text += " public " + containerType.javaName + "(" + javaName + " value) { this(1); put(0, value); }\n"; } @@ -363,7 +369,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio valueNames2 += separator + "value" + n; separator = ", "; n++; - } else for (String javaName : type.javaNames != null ? type.javaNames : new String[] {type.javaName}) { + } else for (String javaName : type.javaNames != null ? uniq(type.javaNames) : new String[] {type.javaName}) { // variant, optional, etc if (!javaName.substring(javaName.indexOf(' ') + 1).equals("Pointer")) { decl.text += " public " + containerType.javaName + "(" + javaName + " value) { this(); put(value); }\n"; @@ -416,6 +422,8 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio + " public native " + containerType.javaName + " first(" + params + separator + removeAnnotations(firstType.javaName) + " first);\n" + " " + indexAnnotation + "public native " + secondType.annotations + secondType.javaName + " second(" + params + "); " + " public native " + containerType.javaName + " second(" + params + separator + removeAnnotations(secondType.javaName) + " second);\n"; + firstType.javaNames = uniq(firstType.javaNames); + secondType.javaNames = uniq(secondType.javaNames); for (int i = 1; !constant && firstType.javaNames != null && i < firstType.javaNames.length; i++) { decl.text += " @MemberSetter @Index" + indexFunction + " public native " + containerType.javaName + " first(" + params + separator + firstType.annotations + firstType.javaNames[i] + " first);\n"; } @@ -433,6 +441,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio if (!constant) { decl.text += " public native " + containerType.javaName + " put(" + params + separator + removeAnnotations(valueType.javaName) + " value);\n"; } + valueType.javaNames = uniq(valueType.javaNames); for (int i = 1; !constant && valueType.javaNames != null && i < valueType.javaNames.length; i++) { decl.text += " @ValueSetter @Index" + indexFunction + " public native " + containerType.javaName + " put(" + params + separator + valueType.annotations + valueType.javaNames[i] + " value);\n"; } @@ -452,6 +461,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio if (!constant && !tuple) { decl.text += " @ValueSetter public native " + containerType.javaName + " put(" + type.annotations + type.javaName + " value);\n"; } + type.javaNames = uniq(type.javaNames); for (int i = 1; !constant && !tuple && type.javaNames != null && i < type.javaNames.length; i++) { decl.text += " @ValueSetter public native " + containerType.javaName + " put(" + type.annotations + type.javaNames[i] + " value);\n"; } @@ -532,8 +542,8 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio } if (!constant && (dim == 0 || (containerType.arguments.length == 1 && indexType != null)) && firstType != null && secondType != null) { - String[] firstNames = firstType.javaNames != null ? firstType.javaNames : new String[] {firstType.javaName}; - String[] secondNames = secondType.javaNames != null ? secondType.javaNames : new String[] {secondType.javaName}; + String[] firstNames = firstType.javaNames != null ? uniq(firstType.javaNames) : new String[] {firstType.javaName}; + String[] secondNames = secondType.javaNames != null ? uniq(secondType.javaNames) : new String[] {secondType.javaName}; String brackets = arrayBrackets + (dim > 0 ? "[]" : ""); for (int n = 0; n < firstNames.length || n < secondNames.length; n++) { String firstName = firstNames[Math.min(n, firstNames.length - 1)]; @@ -566,7 +576,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio } } else if (resizable && firstType == null && secondType == null) { boolean first = true; - for (String javaName : valueType.javaNames != null ? valueType.javaNames : new String[] {valueType.javaName}) { + for (String javaName : valueType.javaNames != null ? uniq(valueType.javaNames) : new String[] {valueType.javaName}) { javaName = removeAnnotations(javaName); decl.text += "\n"; if (dim < 2) { From 4a0f73820d2093bccf2b5d5a280e0cab66dc3dad Mon Sep 17 00:00:00 2001 From: Samuel Audet Date: Tue, 30 Jan 2024 21:51:55 +0900 Subject: [PATCH 2/2] Update CHANGELOG.md and fix nits --- CHANGELOG.md | 2 ++ .../org/bytedeco/javacpp/tools/Parser.java | 35 +++++++++---------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 975958bc..49fb6d5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ + * Prevent `Parser` from producing duplicate declarations for basic containers ([pull #741](https://github.com/bytedeco/javacpp/pull/741)) + ### January 29, 2024 version 1.5.10 * Move native `Loader` methods to `Helper` class to avoid deadlocks ([issue #737](https://github.com/bytedeco/javacpp/issues/737)) * Fix `Parser` failing to pick up `Info` for constructors with template arguments ([pull #739](https://github.com/bytedeco/javacpp/pull/739)) diff --git a/src/main/java/org/bytedeco/javacpp/tools/Parser.java b/src/main/java/org/bytedeco/javacpp/tools/Parser.java index c431d026..65046ca8 100644 --- a/src/main/java/org/bytedeco/javacpp/tools/Parser.java +++ b/src/main/java/org/bytedeco/javacpp/tools/Parser.java @@ -106,7 +106,7 @@ public Parser(Logger logger, Properties properties, String encoding, String line /** Java names of classes recognized as polymorphic. */ Set polymorphicClasses = new HashSet<>(); - private void addDowncast(String base, Type from, boolean virtual) { + void addDowncast(String base, Type from, boolean virtual) { Map inheritance = downcasts.get(base); if (inheritance == null) { downcasts.put(base, inheritance = new HashMap<>(1)); @@ -114,6 +114,11 @@ private void addDowncast(String base, Type from, boolean virtual) { inheritance.put(from, virtual); } + /** De-deduplicate an array of strings, keeping order. */ + static String[] removeDuplicates(String[] a) { + return a != null && a.length > 1 ? new LinkedHashSet<>(Arrays.asList(a)).toArray(new String[0]) : a; + } + static String removeAnnotations(String s) { return s.substring(s.lastIndexOf(' ') + 1); } @@ -181,12 +186,6 @@ String translate(String text) { return text; } - /** De-deduplicate an array of strings, keeping order. */ - private static String[] uniq(String[] a) { - if (a == null || a.length <= 1) return a; - return new LinkedHashSet<>(Arrays.asList(a)).toArray(new String[0]); - } - void containers(Context context, DeclarationList declList) throws ParserException { List basicContainers = new ArrayList<>(); for (Info info : infoMap.get("basic/containers")) { @@ -345,8 +344,8 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio + " public " + containerType.javaName + "(Pointer p) { super(p); }\n"; boolean purify = info != null && info.purify; if (!constant && !purify && (dim == 0 || (containerType.arguments.length == 1 && indexType != null)) && firstType != null && secondType != null) { - String[] firstNames = firstType.javaNames != null ? uniq(firstType.javaNames) : new String[] {firstType.javaName}; - String[] secondNames = secondType.javaNames != null ? uniq(secondType.javaNames) : new String[] {secondType.javaName}; + String[] firstNames = firstType.javaNames != null ? removeDuplicates(firstType.javaNames) : new String[] {firstType.javaName}; + String[] secondNames = secondType.javaNames != null ? removeDuplicates(secondType.javaNames) : new String[] {secondType.javaName}; String brackets = arrayBrackets + (dim > 0 ? "[]" : ""); for (int n = 0; n < firstNames.length || n < secondNames.length; n++) { decl.text += " public " + containerType.javaName + "(" + firstNames[Math.min(n, firstNames.length - 1)] + brackets + " firstValue, " @@ -354,7 +353,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio + "{ this(" + (dim > 0 ? "Math.min(firstValue.length, secondValue.length)" : "") + "); put(firstValue, secondValue); }\n"; } } else if (resizable && !purify && firstType == null && secondType == null) { - for (String javaName : valueType.javaNames != null ? uniq(valueType.javaNames) : new String[] {valueType.javaName}) { + for (String javaName : valueType.javaNames != null ? removeDuplicates(valueType.javaNames) : new String[] {valueType.javaName}) { if (dim < 2 && !javaName.equals("int") && !javaName.equals("long")) { decl.text += " public " + containerType.javaName + "(" + javaName + " value) { this(1); put(0, value); }\n"; } @@ -369,7 +368,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio valueNames2 += separator + "value" + n; separator = ", "; n++; - } else for (String javaName : type.javaNames != null ? uniq(type.javaNames) : new String[] {type.javaName}) { + } else for (String javaName : type.javaNames != null ? removeDuplicates(type.javaNames) : new String[] {type.javaName}) { // variant, optional, etc if (!javaName.substring(javaName.indexOf(' ') + 1).equals("Pointer")) { decl.text += " public " + containerType.javaName + "(" + javaName + " value) { this(); put(value); }\n"; @@ -422,8 +421,8 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio + " public native " + containerType.javaName + " first(" + params + separator + removeAnnotations(firstType.javaName) + " first);\n" + " " + indexAnnotation + "public native " + secondType.annotations + secondType.javaName + " second(" + params + "); " + " public native " + containerType.javaName + " second(" + params + separator + removeAnnotations(secondType.javaName) + " second);\n"; - firstType.javaNames = uniq(firstType.javaNames); - secondType.javaNames = uniq(secondType.javaNames); + firstType.javaNames = removeDuplicates(firstType.javaNames); + secondType.javaNames = removeDuplicates(secondType.javaNames); for (int i = 1; !constant && firstType.javaNames != null && i < firstType.javaNames.length; i++) { decl.text += " @MemberSetter @Index" + indexFunction + " public native " + containerType.javaName + " first(" + params + separator + firstType.annotations + firstType.javaNames[i] + " first);\n"; } @@ -441,7 +440,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio if (!constant) { decl.text += " public native " + containerType.javaName + " put(" + params + separator + removeAnnotations(valueType.javaName) + " value);\n"; } - valueType.javaNames = uniq(valueType.javaNames); + valueType.javaNames = removeDuplicates(valueType.javaNames); for (int i = 1; !constant && valueType.javaNames != null && i < valueType.javaNames.length; i++) { decl.text += " @ValueSetter @Index" + indexFunction + " public native " + containerType.javaName + " put(" + params + separator + valueType.annotations + valueType.javaNames[i] + " value);\n"; } @@ -461,7 +460,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio if (!constant && !tuple) { decl.text += " @ValueSetter public native " + containerType.javaName + " put(" + type.annotations + type.javaName + " value);\n"; } - type.javaNames = uniq(type.javaNames); + type.javaNames = removeDuplicates(type.javaNames); for (int i = 1; !constant && !tuple && type.javaNames != null && i < type.javaNames.length; i++) { decl.text += " @ValueSetter public native " + containerType.javaName + " put(" + type.annotations + type.javaNames[i] + " value);\n"; } @@ -542,8 +541,8 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio } if (!constant && (dim == 0 || (containerType.arguments.length == 1 && indexType != null)) && firstType != null && secondType != null) { - String[] firstNames = firstType.javaNames != null ? uniq(firstType.javaNames) : new String[] {firstType.javaName}; - String[] secondNames = secondType.javaNames != null ? uniq(secondType.javaNames) : new String[] {secondType.javaName}; + String[] firstNames = firstType.javaNames != null ? removeDuplicates(firstType.javaNames) : new String[] {firstType.javaName}; + String[] secondNames = secondType.javaNames != null ? removeDuplicates(secondType.javaNames) : new String[] {secondType.javaName}; String brackets = arrayBrackets + (dim > 0 ? "[]" : ""); for (int n = 0; n < firstNames.length || n < secondNames.length; n++) { String firstName = firstNames[Math.min(n, firstNames.length - 1)]; @@ -576,7 +575,7 @@ void containers(Context context, DeclarationList declList) throws ParserExceptio } } else if (resizable && firstType == null && secondType == null) { boolean first = true; - for (String javaName : valueType.javaNames != null ? uniq(valueType.javaNames) : new String[] {valueType.javaName}) { + for (String javaName : valueType.javaNames != null ? removeDuplicates(valueType.javaNames) : new String[] {valueType.javaName}) { javaName = removeAnnotations(javaName); decl.text += "\n"; if (dim < 2) {