diff --git a/README.md b/README.md index 754cbf12..8d57c5ab 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ The library will remain open source and MIT licensed and can still be used, fork - Fixed possible NullPointerException in SASL auth ([#294](https://github.com/hypfvieh/dbus-java/issues/294)) - Fixed SASL authentication issue when running in server mode in combination with unix sockets ([#298](https://github.com/hypfvieh/dbus-java/issues/298)) - Fixed various issues with `InterfaceCodeGenerator` ([#302](https://github.com/hypfvieh/dbus-java/issues/302), [#303](https://github.com/hypfvieh/dbus-java/issues/303), [#304], (https://github.com/hypfvieh/dbus-java/issues/304), [#306](https://github.com/hypfvieh/dbus-java/issues/306) + - Refactoring and overhaul of `InterfaceCodeGenerator` to improve code, reduce duplications and allow easier fixing/extending ##### Changes in 5.2.0 (2025-12-21): - removed properties from dbus-java.version which causes issues with reproducable builds ([PR#279](https://github.com/hypfvieh/dbus-java/issues/279)) diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGenerator.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGenerator.java index af9d78a1..5952aa5a 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGenerator.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGenerator.java @@ -270,7 +270,7 @@ private List extractSignals(Element _signalElement, ClassBuild } - ClassConstructor classConstructor = new ClassConstructor(_clzBldr, className); + ClassConstructor classConstructor = new ClassConstructor(_clzBldr, 0, className); classConstructor.getArguments().addAll(argsList); classConstructor.getThrowArguments().add(DBusException.class.getSimpleName()); @@ -487,7 +487,7 @@ private List extractProperties(Element _propertyElement, Class if (DBusProperty.Access.WRITE.getAccessName().equals(attrAccess) || DBusProperty.Access.READ_WRITE.getAccessName().equals(attrAccess)) { - ClassMethod classMethod = new SetterMethod(_clzBldr, attrName, rtnType); + ClassMethod classMethod = new SetterMethod(_clzBldr, 0, attrName, rtnType); classMethod.getArguments().add(new MemberOrArgument(_clzBldr, attrName.substring(0, 1).toLowerCase() + attrName.substring(1), clzzName)); _clzBldr.getMethods().add(classMethod); @@ -544,10 +544,10 @@ private String createTuple(List _outputArgs, String _className genericTypes.put(genericName, entry.getType()); entry.getAnnotations().add(new AnnotationInfo(Position.class, AnnotArgs.create().add(position++))); entry.setType(genericName); - cnstrctArgs.add(new MemberOrArgument(_parentClzBldr, entry.getName(), genericName)); + cnstrctArgs.add(new MemberOrArgument(info, entry.getName(), genericName)); } - ClassConstructor cnstrct = new ClassConstructor(_parentClzBldr, _className); + ClassConstructor cnstrct = new ClassConstructor(info, 0, _className); cnstrct.getArguments().addAll(cnstrctArgs); info.getConstructors().add(cnstrct); @@ -609,7 +609,7 @@ private String buildStructClass(List _dbusTypeStr, String _structName, root.setExtendClass(Struct.class.getName()); root.setClassType(ClassType.CLASS); - ClassConstructor classConstructor = new ClassConstructor(_clzBldr, className); + ClassConstructor classConstructor = new ClassConstructor(_clzBldr, 0, className); root.getConstructors().add(classConstructor); String structFqcn = _clzBldr.getPackageName() + "." + Util.upperCaseFirstChar(_structName); diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/StructTreeBuilder.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/StructTreeBuilder.java index 0552d29f..0f299226 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/StructTreeBuilder.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/StructTreeBuilder.java @@ -93,7 +93,7 @@ public String buildStructClasses(String _dbusSig, String _structBaseFqcn, ClassB } if (!treeItem.getSubType().isEmpty()) { - createNested(treeItem.getSubType(), _structBaseFqcn, root, _generatedClasses); + createNested(1, treeItem.getSubType(), _structBaseFqcn, root, _generatedClasses); } } @@ -123,6 +123,7 @@ static String findNextStructFqcn(String _structFqcn, Set _generatedStruc /** * Create nested Struct class. * + * @param _nestedLevel nested depth level * @param _list List of struct tree elements * @param _structFqcnBase base classname of created struct class * @param _root root class of this struct (maybe other struct) @@ -130,12 +131,12 @@ static String findNextStructFqcn(String _structFqcn, Set _generatedStruc * * @return last created struct or null */ - private ClassBuilderInfo createNested(List _list, String _structFqcnBase, ClassBuilderInfo _root, List _classes) { + private ClassBuilderInfo createNested(int _nestedLevel, List _list, String _structFqcnBase, ClassBuilderInfo _root, List _classes) { int position = 0; ClassBuilderInfo root = _root; ClassBuilderInfo retval = null; - ClassConstructor classConstructor = new ClassConstructor(_root, root.getClassName()); + ClassConstructor classConstructor = new ClassConstructor(_root, _nestedLevel, root.getClassName()); for (StructTree inTree : _list) { @@ -158,7 +159,7 @@ private ClassBuilderInfo createNested(List _list, String _structFqcn temp.setClassType(ClassType.CLASS); classConstructor.getArguments().add(new MemberOrArgument(_root, constructorArg, temp.getClassName())); member.setType(temp.getClassName()); - createNested(inTree.getSubType(), _structFqcnBase, temp, _classes); + createNested(_nestedLevel + 1, inTree.getSubType(), _structFqcnBase, temp, _classes); _classes.add(temp); retval = temp; @@ -167,7 +168,7 @@ private ClassBuilderInfo createNested(List _list, String _structFqcn temp.setClassName(root.getClassName()); temp.setPackageName(root.getPackageName()); - ClassBuilderInfo x = createNested(inTree.getSubType(), _structFqcnBase, temp, _classes); + ClassBuilderInfo x = createNested(_nestedLevel + 1, inTree.getSubType(), _structFqcnBase, temp, _classes); if (x != null) { member.getGenerics().add(x.getClassName()); } else { diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassBuilderInfo.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassBuilderInfo.java index fd9bde8e..ada0ce88 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassBuilderInfo.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassBuilderInfo.java @@ -253,13 +253,12 @@ private List createClassFileContent(boolean _staticClass, Set _o } } + List allMethods = new ArrayList<>(getMethods()); + // add getter and setter - for (MemberOrArgument member : members) { - addEmptyLineIfNeeded(content); - content.addAll(member.generate(memberIndentCnt)); - } + getMembers().stream().map(e -> e.generateMethods(memberIndentCnt)).forEach(allMethods::addAll); - for (ClassMethod mth : getMethods()) { + for (ClassMethod mth : allMethods) { addEmptyLineIfNeeded(content); content.addAll(mth.generate(memberIndentCnt)); } diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassConstructor.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassConstructor.java index 99e9c321..8557eb37 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassConstructor.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassConstructor.java @@ -29,10 +29,12 @@ public class ClassConstructor implements ICodeGenerator { private final ClassBuilderInfo classBuilderInfo; private final String className; + private final int indentLevel; - public ClassConstructor(ClassBuilderInfo _bldr, String _className) { + public ClassConstructor(ClassBuilderInfo _bldr, int _indentLevel, String _className) { classBuilderInfo = _bldr; className = _className; + indentLevel = _indentLevel; } public List getThrowArguments() { @@ -58,7 +60,7 @@ public ClassBuilderInfo getClassBuilderInfo() { @Override public List generate(int _indentLevel) { - + int indent = Math.max(indentLevel, _indentLevel); List filteredSuperArguments = new ArrayList<>(getSuperArguments()); filteredSuperArguments.removeIf(e -> getArguments().contains(e)); String constructorArgs = ""; @@ -81,14 +83,14 @@ public List generate(int _indentLevel) { String prefix = getClassBuilderInfo().getArgumentPrefix(); if (!getSuperArguments().isEmpty()) { - assignments = getIndent(_indentLevel / 2) + "super(" + getSuperArguments().stream() + assignments = getIndent(indent / 2) + "super(" + getSuperArguments().stream() .map(e -> ClassBuilderInfo.maybePrefix(e.getName(), prefix)) .collect(Collectors.joining(", ")) + ");" + System.lineSeparator(); } if (!getArguments().isEmpty()) { List assigns = new ArrayList<>(); - String innerIndent = getIndent(_indentLevel / 2); + String innerIndent = getIndent(indent); for (MemberOrArgument e : getArguments()) { assigns.add(innerIndent + "this." + e.getName() + " = " + ClassBuilderInfo.maybePrefix(e.getName(), prefix) + ";"); } @@ -96,7 +98,7 @@ public List generate(int _indentLevel) { } return CONSTRUCTOR_TEMPL.formatted(getClassName(), constructorArgs, throwArgs, assignments) - .lines().map(l -> getIndent(_indentLevel) + l).toList(); + .lines().map(l -> getIndent(indent) + l).toList(); } public String argumentsAsString() { diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassMethod.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassMethod.java index dd148908..ce32ad11 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassMethod.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/ClassMethod.java @@ -111,7 +111,9 @@ public List generate(int _indentLevel) { // add "name" definition if original name differs from reformatted name // e.g. some-name != someName - if (!reformatName().equals(getName())) { + String reformattedMethodName = reformatName(); + if (!reformattedMethodName.equals(getName()) + || !Util.upperCaseFirstChar(getName()).equals(reformattedMethodName)) { currentAnnotations.stream().filter(e -> e.getAnnotationClass() == DBusBoundProperty.class) .forEach(e -> e.getAnnotationParams().put("name", getName())); @@ -126,7 +128,7 @@ public List generate(int _indentLevel) { result.addAll(currentAnnotations.stream().map(a -> getIndent(_indentLevel) + a.getAnnotationString()).toList()); } - String publicModifier = getClassBuilderInfo().getClassType() != ClassType.INTERFACE ? "public " : ""; + String publicModifier = getClassBuilderInfo().getClassType() != ClassType.INTERFACE ? "public" : ""; String mthReturnType = getReturnType() == null ? "void" : TypeConverter.getProperJavaClass(getReturnType(), getClassBuilderInfo().getImports()); String args = ""; @@ -143,7 +145,7 @@ public List generate(int _indentLevel) { } protected List formatMethod(int _indentLvl, String _modifier, String _returnType, String _methodName, String _args) { - return METHOD_TEMPL.formatted(_modifier, _returnType, _methodName, _args) + return METHOD_TEMPL.formatted(Util.isBlank(_modifier) ? "" : " " + _modifier, _returnType, _methodName, _args) .lines().map(l -> getIndent(_indentLvl) + l).toList(); } diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/GetterMethod.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/GetterMethod.java index a8eb4210..9945f7f2 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/GetterMethod.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/GetterMethod.java @@ -11,27 +11,30 @@ public class GetterMethod extends ClassMethod { """; private final MemberOrArgument argument; + private final int indentLevel; + public GetterMethod(ClassBuilderInfo _bldr, String _name, String _returnType) { - this(_bldr, _name, _returnType, null); + this(_bldr, 0, _name, _returnType, null); } - public GetterMethod(ClassBuilderInfo _bldr, String _name, String _returnType, MemberOrArgument _arguments) { + public GetterMethod(ClassBuilderInfo _bldr, int _indentLevel, String _name, String _returnType, MemberOrArgument _arguments) { super(_bldr, _name, _returnType, "boolean".equalsIgnoreCase(_returnType) ? "is" : "get", false); this.argument = _arguments; + this.indentLevel = _indentLevel; } @Override protected List formatMethod(int _indentLvl, String _modifier, String _returnType, String _methodName, String _args) { - + int indent = Math.max(_indentLvl, indentLevel); if (argument == null) { - return super.formatMethod(_indentLvl, _modifier, _returnType, _methodName, _args); + return super.formatMethod(indent, _modifier, _returnType, _methodName, _args); } String content = String.format("return %s;", argument.getName()); - return GETTER_METHOD_TEMPL.formatted(_modifier, _returnType, _methodName, _args, - getIndent(Math.min(1, _indentLvl - 1)), content) - .lines().map(l -> getIndent(_indentLvl) + l).toList(); + return GETTER_METHOD_TEMPL.formatted("public ", _returnType, _methodName, _args, + getIndent(indent), content) + .lines().map(l -> getIndent(indent) + l).toList(); } } diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/MemberOrArgument.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/MemberOrArgument.java index d6e3f18f..45df1258 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/MemberOrArgument.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/MemberOrArgument.java @@ -14,7 +14,7 @@ * @author hypfvieh * @since v3.0.1 - 2018-12-20 */ -public class MemberOrArgument implements ICodeGenerator { +public class MemberOrArgument { /** Name of member/field. */ private final String name; @@ -78,25 +78,25 @@ public String getFullType(Set _allImports) { return sb.toString(); } - @Override public ClassBuilderInfo getClassBuilderInfo() { return classBuilderInfo; } - @Override - public List generate(int _indentLevel) { - List result = new ArrayList<>(); + public List generateMethods(int _indentLevel) { + List result = new ArrayList<>(); String memberType = TypeConverter.getProperJavaClass(getType(), getClassBuilderInfo().getImports()); if (!getGenerics().isEmpty()) { - memberType += "<" + getGenerics().stream().map(c -> TypeConverter.convertJavaType(c, false)).collect(Collectors.joining(", ")) + ">"; + memberType += "<" + getGenerics().stream() + .map(c -> TypeConverter.convertJavaType(c, false)) + .collect(Collectors.joining(", ")) + ">"; } - GetterMethod getterMethod = new GetterMethod(getClassBuilderInfo(), getName(), memberType, this); + GetterMethod getterMethod = new GetterMethod(getClassBuilderInfo(), _indentLevel, getName(), memberType, this); + result.add(getterMethod); - getClassBuilderInfo().getMethods().add(getterMethod); if (!isFinalArg()) { - getClassBuilderInfo().getMethods().add(new SetterMethod(getClassBuilderInfo(), getName(), memberType)); + result.add(new SetterMethod(getClassBuilderInfo(), _indentLevel, getName(), memberType)); } return result; diff --git a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/SetterMethod.java b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/SetterMethod.java index 52b91fa4..a0f57638 100644 --- a/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/SetterMethod.java +++ b/dbus-java-utils/src/main/java/org/freedesktop/dbus/utils/generator/type/SetterMethod.java @@ -9,23 +9,26 @@ public class SetterMethod extends ClassMethod { %s%s } """; + private final int indentLevel; - public SetterMethod(ClassBuilderInfo _bldr, String _name, String _setterType) { + public SetterMethod(ClassBuilderInfo _bldr, int _indentLevel, String _name, String _setterType) { super(_bldr, _name, "void", "set", false); + indentLevel = _indentLevel; getArguments().add(new MemberOrArgument(_bldr, _name, _setterType)); } @Override protected List formatMethod(int _indentLvl, String _modifier, String _returnType, String _methodName, String _args) { + int indent = Math.max(indentLevel, _indentLvl); if (getArguments() == null || getArguments().isEmpty()) { - return super.formatMethod(_indentLvl, _modifier, _returnType, _methodName, _args); + return super.formatMethod(indent, _modifier, _returnType, _methodName, _args); } String content = String.format("this.%s = %s;", getArguments().getFirst().getName(), getArguments().getFirst().getName()); - return SETTER_METHOD_TEMPL.formatted(_modifier, _returnType, _methodName, _args, - getIndent(Math.min(1, _indentLvl - 1)), content) - .lines().map(l -> getIndent(_indentLvl) + l).toList(); + return SETTER_METHOD_TEMPL.formatted("public ", _returnType, _methodName, _args, + getIndent(indent), content) + .lines().map(l -> getIndent(indent) + l).toList(); } } diff --git a/dbus-java-utils/src/test/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGeneratorTest.java b/dbus-java-utils/src/test/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGeneratorTest.java index 004dac3d..97bdd1bc 100644 --- a/dbus-java-utils/src/test/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGeneratorTest.java +++ b/dbus-java-utils/src/test/java/org/freedesktop/dbus/utils/generator/InterfaceCodeGeneratorTest.java @@ -87,7 +87,7 @@ void testHandleKebabCase() throws Exception { assertLineEquals(12, clzContent, " @DBusBoundProperty(name = \"power-saver-enabled\")"); assertLineEquals(13, clzContent, " boolean isPowerSaverEnabled();"); - assertLineEquals(15, clzContent, " @DBusBoundProperty"); + assertLineEquals(15, clzContent, " @DBusBoundProperty(name = \"version\")"); assertLineEquals(16, clzContent, " UInt32 getVersion();"); } @@ -168,6 +168,65 @@ void testIssue306() throws Exception { assertLineEquals(22, clzContent, " @DBusBoundProperty(type = PropertySupportedOptionsType.class)"); } + @Test + void testStructFormatting() throws Exception { + InterfaceCodeGenerator ci2 = loadDBusXmlFile(true, + new File("src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Usb.xml"), + "/", "org.freedesktop.portal.Usb"); + Map analyze = ci2.analyze(true); + + assertEquals(6, analyze.size()); + + String clzContent = analyze.entrySet().stream() + .filter(e -> e.getKey().getName().equals("AcquireDevicesDevicesStruct.java")) + .findFirst() + .map(e -> e.getValue()) + .orElseThrow(); + + assertLineEquals(16, clzContent, " public AcquireDevicesDevicesStruct(String member0, Map> member1) {"); + assertLineEquals(17, clzContent, " this.member0 = member0;"); + assertLineEquals(18, clzContent, " this.member1 = member1;"); + + assertLineEquals(21, clzContent, " public String getMember0() {"); + assertLineEquals(22, clzContent, " return member0;"); + + assertLineEquals(25, clzContent, " public Map> getMember1() {"); + assertLineEquals(26, clzContent, " return member1;"); + } + + @Test + void testTupleFormatting() throws Exception { + InterfaceCodeGenerator ci2 = loadDBusXmlFile(true, + new File("src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Documents.xml"), + "/", "org.freedesktop.portal.Documents"); + Map analyze = ci2.analyze(true); + + assertEquals(4, analyze.size()); + + String clzContent = analyze.entrySet().stream() + .filter(e -> e.getKey().getName().equals("AddFullTuple.java")) + .findFirst() + .map(e -> e.getValue()) + .orElseThrow(); + + assertLineEquals(14, clzContent, " public AddFullTuple(A docIds, B extraOut) {"); + assertLineEquals(15, clzContent, " this.docIds = docIds;"); + assertLineEquals(16, clzContent, " this.extraOut = extraOut;"); + + assertLineEquals(19, clzContent, " public A getDocIds() {"); + assertLineEquals(20, clzContent, " return docIds;"); + + assertLineEquals(23, clzContent, " public void setDocIds(A docIds) {"); + assertLineEquals(24, clzContent, " this.docIds = docIds;"); + + assertLineEquals(27, clzContent, " public B getExtraOut() {"); + assertLineEquals(28, clzContent, " return extraOut;"); + + assertLineEquals(31, clzContent, " public void setExtraOut(B extraOut) {"); + assertLineEquals(32, clzContent, " this.extraOut = extraOut;"); + + } + @Test void testCreateSampleStructArgs() throws Exception { InterfaceCodeGenerator ci2 = loadDBusXmlFile( diff --git a/dbus-java-utils/src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Documents.xml b/dbus-java-utils/src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Documents.xml new file mode 100644 index 00000000..4e2b2646 --- /dev/null +++ b/dbus-java-utils/src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Documents.xml @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dbus-java-utils/src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Usb.xml b/dbus-java-utils/src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Usb.xml new file mode 100644 index 00000000..2e56e56e --- /dev/null +++ b/dbus-java-utils/src/test/resources/CreateInterface/xdg-desktop/org.freedesktop.portal.Usb.xml @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +