From a67282a8cbab294f7d8769599af42f82e10b7885 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Fri, 21 Jul 2017 05:21:29 +0300 Subject: [PATCH 01/19] Removed nb-configuration.xml. The jdkPlatform property is causing compiling issues for many developers and isn't needed anyway. --- nb-configuration.xml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 nb-configuration.xml diff --git a/nb-configuration.xml b/nb-configuration.xml deleted file mode 100644 index a65c451..0000000 --- a/nb-configuration.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - JDK_1.8 - - From ca70cf9eba70a49e1b3451ffec2a23e045568420 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Fri, 21 Jul 2017 05:25:24 +0300 Subject: [PATCH 02/19] Moved plugin to same category as other JavaFX plugins. --- src/main/resources/com/lynden/netbeans/javafx/Bundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/com/lynden/netbeans/javafx/Bundle.properties b/src/main/resources/com/lynden/netbeans/javafx/Bundle.properties index 311c424..8b4629e 100644 --- a/src/main/resources/com/lynden/netbeans/javafx/Bundle.properties +++ b/src/main/resources/com/lynden/netbeans/javafx/Bundle.properties @@ -2,5 +2,5 @@ OpenIDE-Module-Name=JavaFx Property Getter & Setter Generator OpenIDE-Module-Short-Description=Automatically generates getter and setter methods for JavaFx Properties in a POJO. OpenIDE-Module-Long-Description=Automatically generates getter and setter methods for JavaFx Properties in a POJO. -OpenIDE-Module-Display-Category=JavaFx +OpenIDE-Module-Display-Category=JavaFX 2 #Tue Sep 29 14:37:09 PDT 2015 From 48c13bf9fc34e61deba7470d679f72c6a62687a9 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Fri, 21 Jul 2017 06:07:07 +0300 Subject: [PATCH 03/19] Run the code through reformatter. Apparently committer @kunstmusik used tabs for indentation while the rest of the code used 4 spaces. Everything uses 4 spaces now. --- .../javafx/CodeGeneratorCancellableTask.java | 50 ++++---- .../netbeans/javafx/JavaFxBeanHelper.java | 24 ++-- .../lynden/netbeans/javafx/PackageHelper.java | 53 ++++---- .../javafx/PropertyMethodBuilder.java | 117 +++++++++--------- .../lynden/netbeans/javafx/TreeHelper.java | 48 +++---- 5 files changed, 142 insertions(+), 150 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java b/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java index e3922e1..1d9c1f8 100644 --- a/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java +++ b/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java @@ -1,29 +1,28 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Lynden, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.lynden.netbeans.javafx; -/** -The MIT License (MIT) - -Copyright (c) 2015 Lynden, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -**/ - import com.sun.source.tree.ClassTree; import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; @@ -38,6 +37,7 @@ of this software and associated documentation files (the "Software"), to deal * @author Francesco Illuminati */ abstract class CodeGeneratorCancellableTask implements CancellableTask { + private final JTextComponent textComponent; public CodeGeneratorCancellableTask(JTextComponent textComponent) { @@ -58,7 +58,7 @@ private void generate(WorkingCopy wc) throws IOException { final int caretOffset = textComponent.getCaretPosition(); TreePath path = wc.getTreeUtilities().pathFor(caretOffset); path = TreeHelper.getParentElementOfKind(Tree.Kind.CLASS, path); - int idx = TreeHelper.findClassMemberIndex(wc,(ClassTree) path.getLeaf(), caretOffset); + int idx = TreeHelper.findClassMemberIndex(wc, (ClassTree) path.getLeaf(), caretOffset); generateCode(wc, path, idx); } diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index ce67324..7bf9855 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -1,4 +1,4 @@ -/** +/* * The MIT License (MIT) * * Copyright (c) 2015 Lynden, Inc. @@ -20,7 +20,6 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. -* */ package com.lynden.netbeans.javafx; @@ -171,12 +170,12 @@ private List getFields(Lookup context, CompilationController co for (VariableElement e : temp) { try { Class memberClass = Class.forName(getClassName(e.asType().toString())); - if (Property.class.isAssignableFrom(memberClass) && - !ListProperty.class.isAssignableFrom(memberClass) && - !MapProperty.class.isAssignableFrom(memberClass) && - !ObjectProperty.class.isAssignableFrom(memberClass) && - !SetProperty.class.isAssignableFrom(memberClass) ) { - + if (Property.class.isAssignableFrom(memberClass) + && !ListProperty.class.isAssignableFrom(memberClass) + && !MapProperty.class.isAssignableFrom(memberClass) + && !ObjectProperty.class.isAssignableFrom(memberClass) + && !SetProperty.class.isAssignableFrom(memberClass)) { + elementList.add(e); } } catch (Exception ex) { @@ -188,13 +187,12 @@ private List getFields(Lookup context, CompilationController co throw new CodeGeneratorException(ex); } } - - - protected String getClassName( String fullName ) { - if( !fullName.contains("<") ) { + + protected String getClassName(String fullName) { + if (!fullName.contains("<")) { return fullName; } else { - return fullName.substring( 0, fullName.indexOf("<") ); + return fullName.substring(0, fullName.indexOf("<")); } } diff --git a/src/main/java/com/lynden/netbeans/javafx/PackageHelper.java b/src/main/java/com/lynden/netbeans/javafx/PackageHelper.java index 566e9fe..2d943ad 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PackageHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/PackageHelper.java @@ -1,27 +1,26 @@ -/** -The MIT License (MIT) - -Copyright (c) 2015 Lynden, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -**/ - +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Lynden, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.lynden.netbeans.javafx; import java.util.ArrayList; @@ -33,10 +32,8 @@ of this software and associated documentation files (the "Software"), to deal */ class PackageHelper { - /** Removes packages from class names (it manages generics too). - * i.e. - * {@code java.lang.String -> String} - * and + /** Removes packages from class names (it manages generics too). i.e. + * {@code java.lang.String -> String} and * {@code java.util.List -> List}. */ static String removePackagesFromGenericsType(String fullName) { diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index 1826d61..20f1b65 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -1,26 +1,26 @@ -/** -The MIT License (MIT) - -Copyright (c) 2015 Lynden, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -**/ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Lynden, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.lynden.netbeans.javafx; import com.sun.source.tree.AnnotationTree; @@ -47,21 +47,21 @@ of this software and associated documentation files (the "Software"), to deal * */ public class PropertyMethodBuilder { - + private static final String PROPERTY = "Property"; // NOI18N - private static final Map PRIMITIVES_MAP; + private static final Map PRIMITIVES_MAP; static { - PRIMITIVES_MAP = new HashMap<>(); - PRIMITIVES_MAP.put("Integer", "int"); - PRIMITIVES_MAP.put("Float", "float"); - PRIMITIVES_MAP.put("Double", "double"); - PRIMITIVES_MAP.put("Boolean", "boolean"); - PRIMITIVES_MAP.put("Long", "long"); + PRIMITIVES_MAP = new HashMap<>(); + PRIMITIVES_MAP.put("Integer", "int"); + PRIMITIVES_MAP.put("Float", "float"); + PRIMITIVES_MAP.put("Double", "double"); + PRIMITIVES_MAP.put("Boolean", "boolean"); + PRIMITIVES_MAP.put("Long", "long"); } private static String replaceWithPrimitive(String typeName) { - return PRIMITIVES_MAP.getOrDefault(typeName, typeName); + return PRIMITIVES_MAP.getOrDefault(typeName, typeName); } private final TreeMaker make; @@ -69,8 +69,6 @@ private static String replaceWithPrimitive(String typeName) { private final List elements; private final String className; - - public PropertyMethodBuilder(TreeMaker make, List members, List elements, @@ -83,7 +81,7 @@ public PropertyMethodBuilder(TreeMaker make, int removeExistingPropMethods(int index) { int counter = 0; - if( elements == null ) { + if (elements == null) { return 0; } for (Iterator treeIt = members.iterator(); treeIt.hasNext();) { @@ -92,17 +90,16 @@ int removeExistingPropMethods(int index) { if (member.getKind().equals(Tree.Kind.METHOD)) { MethodTree mt = (MethodTree) member; for (Element element : elements) { - if( mt.getName().contentEquals(getGetterName(element.getSimpleName().toString()) ) || - mt.getName().contentEquals(getGetterName(element.getSimpleName().toString(), "is") ) || - - mt.getName().contentEquals(getSetterName(element.getSimpleName().toString()) ) || - mt.getName().contentEquals(getPropertyMethodName(element.getSimpleName().toString()))) { - - treeIt.remove(); - if (index > counter) { - index--; - } - break; + if (mt.getName().contentEquals(getGetterName(element.getSimpleName().toString())) + || mt.getName().contentEquals(getGetterName(element.getSimpleName().toString(), "is")) + || mt.getName().contentEquals(getSetterName(element.getSimpleName().toString())) + || mt.getName().contentEquals(getPropertyMethodName(element.getSimpleName().toString()))) { + + treeIt.remove(); + if (index > counter) { + index--; + } + break; } } } @@ -113,10 +110,10 @@ int removeExistingPropMethods(int index) { void addPropMethods(int index) { - if( elements == null ) { + if (elements == null) { return; } - + int position = index - 1; for (VariableElement element : elements) { @@ -133,7 +130,7 @@ void addPropMethods(int index) { protected MethodTree createGetMethod(VariableElement element) { Set modifiers = EnumSet.of(Modifier.PUBLIC, Modifier.FINAL); List annotations = new ArrayList<>(); - String typeName = replaceWithPrimitive(toStringWithoutPackages(element)); + String typeName = replaceWithPrimitive(toStringWithoutPackages(element)); VariableTree parameter = make.Variable(make.Modifiers(new HashSet(), Collections.emptyList()), "value", make.Identifier(typeName), null); @@ -141,7 +138,7 @@ protected MethodTree createGetMethod(VariableElement element) { final String bodyText = createPropGetterMethodBody(element); - String setterPrefix = ("boolean".equals(typeName)) ? "is" : "get"; + String setterPrefix = ("boolean".equals(typeName)) ? "is" : "get"; MethodTree method = make.Method( make.Modifiers(modifiers, annotations), @@ -186,7 +183,7 @@ protected MethodTree createPropertyMethod(VariableElement element) { protected MethodTree createSetMethod(VariableElement element) { Set modifiers = EnumSet.of(Modifier.PUBLIC, Modifier.FINAL); List annotations = new ArrayList<>(); - String typeName = replaceWithPrimitive(toStringWithoutPackages(element)); + String typeName = replaceWithPrimitive(toStringWithoutPackages(element)); VariableTree parameter = make.Variable(make.Modifiers(new HashSet(), Collections.emptyList()), "value", make.Identifier(typeName), null); @@ -239,8 +236,8 @@ void addFields() { for (VariableElement element : elements) { VariableTree field = make.Variable(make.Modifiers( - EnumSet.of(Modifier.PRIVATE), - Collections.emptyList()), + EnumSet.of(Modifier.PRIVATE), + Collections.emptyList()), element.getSimpleName().toString(), make.Identifier(toStringWithoutPackages(element)), null); @@ -253,7 +250,7 @@ private String getPropertyMethodName(String fieldName) { final StringBuilder sb = new StringBuilder(); sb.append(this.prepareFieldNameForMethodName(fieldName, Boolean.FALSE)); sb.append(PROPERTY); - + return sb.toString(); } @@ -261,7 +258,7 @@ private String getSetterName(String fieldName) { final StringBuilder sb = new StringBuilder(); sb.append("set"); sb.append(this.prepareFieldNameForMethodName(fieldName)); - + return sb.toString(); } @@ -273,22 +270,22 @@ private String getGetterName(String fieldName, String prefix) { final StringBuilder sb = new StringBuilder(); sb.append(prefix); sb.append(this.prepareFieldNameForMethodName(fieldName)); - + return sb.toString(); } - + private String prepareFieldNameForMethodName(String fieldName, boolean firstCharToUpperCase) { if (firstCharToUpperCase) { fieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); } - + if (fieldName.endsWith(PROPERTY)) { fieldName = fieldName.substring(0, fieldName.length() - PROPERTY.length()); } - + return fieldName; } - + private String prepareFieldNameForMethodName(String fieldName) { return this.prepareFieldNameForMethodName(fieldName, Boolean.TRUE); } diff --git a/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java b/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java index dbaecb4..d723ec2 100644 --- a/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java @@ -1,27 +1,26 @@ -/** -The MIT License (MIT) - -Copyright (c) 2015 Lynden, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -**/ - +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Lynden, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ package com.lynden.netbeans.javafx; import com.sun.source.tree.ClassTree; @@ -37,6 +36,7 @@ of this software and associated documentation files (the "Software"), to deal * */ class TreeHelper { + /** * Search up the hierarchy of elements for one of the given kind. * From 45e6dc5a7f017c4ed885c6ad5fe01638bdf8c90b Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Fri, 21 Jul 2017 06:15:31 +0300 Subject: [PATCH 04/19] Removed "final" modifier from property getters. Property getter should not be final. See: https://wiki.openjdk.java.net/display/OpenJFX/JavaFX+Property+Architecture#JavaFXPropertyArchitecture-JavaFXSolution --- .../java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index 20f1b65..5556608 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -156,7 +156,7 @@ protected MethodTree createGetMethod(VariableElement element) { } protected MethodTree createPropertyMethod(VariableElement element) { - Set modifiers = EnumSet.of(Modifier.PUBLIC, Modifier.FINAL); + Set modifiers = EnumSet.of(Modifier.PUBLIC); List annotations = new ArrayList<>(); VariableTree parameter = make.Variable(make.Modifiers(new HashSet(), Collections.emptyList()), "value", make.Identifier(toStringWithoutPackages(element)), null); From ad2766622ac3d4625c56a7bace18d48b5aaa284b Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Fri, 21 Jul 2017 07:16:18 +0300 Subject: [PATCH 05/19] Refactored a few Booleans. --- .../com/lynden/netbeans/javafx/PropertyMethodBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index 5556608..0ee0b23 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -248,7 +248,7 @@ void addFields() { private String getPropertyMethodName(String fieldName) { final StringBuilder sb = new StringBuilder(); - sb.append(this.prepareFieldNameForMethodName(fieldName, Boolean.FALSE)); + sb.append(this.prepareFieldNameForMethodName(fieldName, false)); sb.append(PROPERTY); return sb.toString(); @@ -287,7 +287,7 @@ private String prepareFieldNameForMethodName(String fieldName, boolean firstChar } private String prepareFieldNameForMethodName(String fieldName) { - return this.prepareFieldNameForMethodName(fieldName, Boolean.TRUE); + return this.prepareFieldNameForMethodName(fieldName, true); } private static String toStringWithoutPackages(VariableElement element) { From 411345c481b9ce52376e0b17b46eb6c17036a0ef Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sat, 22 Jul 2017 10:34:31 +0300 Subject: [PATCH 06/19] Added support for all writable property types. Support added for: ObjectProperty ListProperty SetProperty MapProperty + refactoring related to the changes. --- .../netbeans/javafx/JavaFxBeanHelper.java | 35 ++-- .../javafx/PropertyMethodBuilder.java | 156 +++++++++--------- 2 files changed, 105 insertions(+), 86 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index 7bf9855..9500073 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -35,6 +35,8 @@ import javafx.embed.swing.JFXPanel; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; import javax.swing.text.Document; @@ -169,16 +171,19 @@ private List getFields(Lookup context, CompilationController co for (VariableElement e : temp) { try { - Class memberClass = Class.forName(getClassName(e.asType().toString())); - if (Property.class.isAssignableFrom(memberClass) - && !ListProperty.class.isAssignableFrom(memberClass) - && !MapProperty.class.isAssignableFrom(memberClass) - && !ObjectProperty.class.isAssignableFrom(memberClass) - && !SetProperty.class.isAssignableFrom(memberClass)) { - - elementList.add(e); + TypeMirror memberType = e.asType(); + + /* Checking if memberType is a class. Otherwise + * Class.forName would throw an error. */ + if (memberType.getKind() == TypeKind.DECLARED) { + + Class memberClass = Class.forName(getClassName(memberType.toString())); + if (Property.class.isAssignableFrom(memberClass)) { + + elementList.add(e); + } } - } catch (Exception ex) { + } catch (ClassNotFoundException ex) { Exceptions.printStackTrace(ex); } } @@ -188,11 +193,19 @@ private List getFields(Lookup context, CompilationController co } } - protected String getClassName(String fullName) { + public static String getClassName(String fullName) { if (!fullName.contains("<")) { return fullName; } else { - return fullName.substring(0, fullName.indexOf("<")); + return fullName.substring(0, fullName.indexOf('<')); + } + } + + public static String getTypeParameters(String fullName) { + if (!fullName.contains("<")) { + return ""; + } else { + return fullName.substring(fullName.indexOf('<') + 1, fullName.lastIndexOf('>')); } } diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index 0ee0b23..e12e005 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -26,18 +26,16 @@ import com.sun.source.tree.AnnotationTree; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.MethodTree; +import com.sun.source.tree.ModifiersTree; import com.sun.source.tree.Tree; import com.sun.source.tree.TypeParameterTree; import com.sun.source.tree.VariableTree; -import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; @@ -49,19 +47,39 @@ public class PropertyMethodBuilder { private static final String PROPERTY = "Property"; // NOI18N - private static final Map PRIMITIVES_MAP; + private static final Map VALUE_TYPES = new HashMap<>(); + private static final Map GENERIC_VALUE_TYPES = new HashMap<>(); static { - PRIMITIVES_MAP = new HashMap<>(); - PRIMITIVES_MAP.put("Integer", "int"); - PRIMITIVES_MAP.put("Float", "float"); - PRIMITIVES_MAP.put("Double", "double"); - PRIMITIVES_MAP.put("Boolean", "boolean"); - PRIMITIVES_MAP.put("Long", "long"); + VALUE_TYPES.put("javafx.beans.property.IntegerProperty", "int"); + VALUE_TYPES.put("javafx.beans.property.LongProperty", "long"); + VALUE_TYPES.put("javafx.beans.property.FloatProperty", "float"); + VALUE_TYPES.put("javafx.beans.property.DoubleProperty", "double"); + VALUE_TYPES.put("javafx.beans.property.BooleanProperty", "boolean"); + VALUE_TYPES.put("javafx.beans.property.StringProperty", "java.lang.String"); + + GENERIC_VALUE_TYPES.put("javafx.beans.property.ListProperty", "javafx.collections.ObservableList"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.SetProperty", "javafx.collections.ObservableSet"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.MapProperty", "javafx.collections.ObservableMap"); } - private static String replaceWithPrimitive(String typeName) { - return PRIMITIVES_MAP.getOrDefault(typeName, typeName); + private static String getValueType(String typeName) { + + String className = JavaFxBeanHelper.getClassName(typeName); + String typeParams = JavaFxBeanHelper.getTypeParameters(typeName); + + if (VALUE_TYPES.containsKey(className)) { + return VALUE_TYPES.get(className); + + } else if (GENERIC_VALUE_TYPES.containsKey(className)) { + return GENERIC_VALUE_TYPES.get(className) + '<' + typeParams + '>'; + + } else if (className.equals("javafx.beans.property.ObjectProperty")) { + return typeParams; + + } else { + return "java.lang.Object"; + } } private final TreeMaker make; @@ -90,9 +108,9 @@ int removeExistingPropMethods(int index) { if (member.getKind().equals(Tree.Kind.METHOD)) { MethodTree mt = (MethodTree) member; for (Element element : elements) { - if (mt.getName().contentEquals(getGetterName(element.getSimpleName().toString())) - || mt.getName().contentEquals(getGetterName(element.getSimpleName().toString(), "is")) - || mt.getName().contentEquals(getSetterName(element.getSimpleName().toString())) + if (mt.getName().contentEquals(getGetMethodName(element.getSimpleName().toString())) + || mt.getName().contentEquals(getGetMethodName(element.getSimpleName().toString(), "is")) + || mt.getName().contentEquals(getSetMethodName(element.getSimpleName().toString())) || mt.getName().contentEquals(getPropertyMethodName(element.getSimpleName().toString()))) { treeIt.remove(); @@ -128,82 +146,70 @@ void addPropMethods(int index) { } protected MethodTree createGetMethod(VariableElement element) { - Set modifiers = EnumSet.of(Modifier.PUBLIC, Modifier.FINAL); - List annotations = new ArrayList<>(); - String typeName = replaceWithPrimitive(toStringWithoutPackages(element)); - VariableTree parameter = make.Variable(make.Modifiers(new HashSet(), Collections.emptyList()), "value", make.Identifier(typeName), - null); + ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)); + + String returnTypeName = getValueType(element.asType().toString()); + Tree returnType = make.Type(returnTypeName); + + String getterPrefix = ("boolean".equals(returnTypeName)) ? "is" : "get"; + String name = getGetMethodName(element.getSimpleName().toString(), getterPrefix); + + List typeParameters = Collections.emptyList(); - ExpressionTree returnType = make.QualIdent(parameter.getType().toString()); + List parameters = Collections.emptyList(); - final String bodyText = createPropGetterMethodBody(element); + List throwsList = Collections.emptyList(); - String setterPrefix = ("boolean".equals(typeName)) ? "is" : "get"; + String body = createGetMethodBody(element); - MethodTree method = make.Method( - make.Modifiers(modifiers, annotations), - getGetterName(element.getSimpleName().toString(), setterPrefix), - returnType, - Collections.emptyList(), - //Collections.singletonList(parameter), - Collections.emptyList(), - Collections.emptyList(), - bodyText, - null); + ExpressionTree defaultValue = null; - return method; + return make.Method(modifiers, name, returnType, typeParameters, parameters, throwsList, body, defaultValue); } protected MethodTree createPropertyMethod(VariableElement element) { - Set modifiers = EnumSet.of(Modifier.PUBLIC); - List annotations = new ArrayList<>(); - VariableTree parameter = make.Variable(make.Modifiers(new HashSet(), Collections.emptyList()), "value", make.Identifier(toStringWithoutPackages(element)), - null); + ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC)); - ExpressionTree returnType = make.QualIdent(parameter.getType().toString() + PROPERTY); + Tree returnType = make.Type(element.asType().toString()); - final String bodyText = createPropertyMethodBody(element); + String name = getPropertyMethodName(element.getSimpleName().toString()); - MethodTree method = make.Method( - make.Modifiers(modifiers, annotations), - getPropertyMethodName(element.getSimpleName().toString()), - returnType, - Collections.emptyList(), - //Collections.singletonList(parameter), - Collections.emptyList(), - Collections.emptyList(), - bodyText, - null); + List typeParameters = Collections.emptyList(); - return method; + List parameters = Collections.emptyList(); + List throwsList = Collections.emptyList(); + + String body = createPropertyMethodBody(element); + + ExpressionTree defaultValue = null; + + + return make.Method(modifiers, name, returnType, typeParameters, parameters, throwsList, body, defaultValue); } protected MethodTree createSetMethod(VariableElement element) { - Set modifiers = EnumSet.of(Modifier.PUBLIC, Modifier.FINAL); - List annotations = new ArrayList<>(); - String typeName = replaceWithPrimitive(toStringWithoutPackages(element)); - VariableTree parameter = make.Variable(make.Modifiers(new HashSet(), Collections.emptyList()), "value", make.Identifier(typeName), - null); + ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)); + + Tree returnType = make.Type("void"); + + String name = getSetMethodName(element.getSimpleName().toString()); + + List typeParameters = Collections.emptyList(); + + String parameterTypeName = getValueType(element.asType().toString()); + VariableTree parameter = make.Variable(make.Modifiers(Collections.emptySet()), "value", make.Type(parameterTypeName), null); + List parameters = Collections.singletonList(parameter); - ExpressionTree returnType = make.QualIdent("void"); + List throwsList = Collections.emptyList(); - final String bodyText = createPropSetterMethodBody(element); + String body = createSetMethodBody(element); - MethodTree method = make.Method( - make.Modifiers(modifiers, annotations), - getSetterName(element.getSimpleName().toString()), - returnType, - Collections.emptyList(), - //Collections.singletonList(parameter), - Collections.singletonList(parameter), - Collections.emptyList(), - bodyText, - null); + ExpressionTree defaultValue = null; - return method; + return make.Method(modifiers, name, returnType, typeParameters, parameters, throwsList, body, defaultValue); } protected String createPropertyMethodBody(Element element) { @@ -215,7 +221,7 @@ protected String createPropertyMethodBody(Element element) { return sb.toString(); } - protected String createPropGetterMethodBody(Element element) { + protected String createGetMethodBody(Element element) { StringBuilder sb = new StringBuilder(); sb.append("{\n") .append("return ") @@ -224,7 +230,7 @@ protected String createPropGetterMethodBody(Element element) { return sb.toString(); } - protected String createPropSetterMethodBody(Element element) { + protected String createSetMethodBody(Element element) { StringBuilder sb = new StringBuilder(); sb.append("{\n") .append(element.getSimpleName()) @@ -254,7 +260,7 @@ private String getPropertyMethodName(String fieldName) { return sb.toString(); } - private String getSetterName(String fieldName) { + private String getSetMethodName(String fieldName) { final StringBuilder sb = new StringBuilder(); sb.append("set"); sb.append(this.prepareFieldNameForMethodName(fieldName)); @@ -262,11 +268,11 @@ private String getSetterName(String fieldName) { return sb.toString(); } - private String getGetterName(String fieldName) { - return getGetterName(fieldName, "get"); + private String getGetMethodName(String fieldName) { + return getGetMethodName(fieldName, "get"); } - private String getGetterName(String fieldName, String prefix) { + private String getGetMethodName(String fieldName, String prefix) { final StringBuilder sb = new StringBuilder(); sb.append(prefix); sb.append(this.prepareFieldNameForMethodName(fieldName)); From 5f2642a29c48cbac2add0feddeca674ec715773b Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sat, 22 Jul 2017 10:39:17 +0300 Subject: [PATCH 07/19] Moved getters first like they are in most documentation. --- .../com/lynden/netbeans/javafx/PropertyMethodBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index e12e005..c22b865 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -135,11 +135,11 @@ void addPropMethods(int index) { int position = index - 1; for (VariableElement element : elements) { - position = Math.min(position + 1, members.size()); - members.add(position, createSetMethod(element)); position = Math.min(position + 1, members.size()); members.add(position, createGetMethod(element)); position = Math.min(position + 1, members.size()); + members.add(position, createSetMethod(element)); + position = Math.min(position + 1, members.size()); members.add(position, createPropertyMethod(element)); } From f1c3e3dd1734bd8b9cf457366a5b54c84eb21e6f Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sat, 22 Jul 2017 20:28:44 +0300 Subject: [PATCH 08/19] Restricted method generation to only supported property classes. Previously all classes implementing "Property" were supported, which led to errors. --- .../netbeans/javafx/JavaFxBeanHelper.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index 9500073..b441bb3 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -30,13 +30,13 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; -import javafx.beans.property.*; +import java.util.Set; +import java.util.stream.Collectors; import javafx.embed.swing.JFXPanel; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; import javax.swing.text.Document; @@ -55,6 +55,21 @@ public class JavaFxBeanHelper implements CodeGenerator { + private static final Set SUPPORTED_CLASSES = new HashSet<>(); + + static { + SUPPORTED_CLASSES.add("javafx.beans.property.IntegerProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.LongProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.FloatProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.DoubleProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.BooleanProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.StringProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ListProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.SetProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.MapProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ObjectProperty"); + } + protected JTextComponent textComponent; //this is needed to initialize the JavaFx Toolkit protected JFXPanel panel = new JFXPanel(); @@ -157,7 +172,6 @@ protected void generateCode(WorkingCopy wc, TreePath path, int position, List getFields(Lookup context, CompilationController controller) throws CodeGeneratorException { try { - List elementList = new ArrayList<>(); TreePath treePath = context.lookup(TreePath.class); TreePath path = TreeHelper.getParentElementOfKind(Tree.Kind.CLASS, treePath); TypeElement typeElement = (TypeElement) controller.getTrees().getElement(path); @@ -167,27 +181,13 @@ private List getFields(Lookup context, CompilationController co } Elements elements = controller.getElements(); - List temp = ElementFilter.fieldsIn(elements.getAllMembers(typeElement)); - - for (VariableElement e : temp) { - try { - TypeMirror memberType = e.asType(); + List allFields = ElementFilter.fieldsIn(elements.getAllMembers(typeElement)); - /* Checking if memberType is a class. Otherwise - * Class.forName would throw an error. */ - if (memberType.getKind() == TypeKind.DECLARED) { + List supportedFields = allFields.stream().filter((VariableElement var) -> { + return SUPPORTED_CLASSES.contains(getClassName(var.asType().toString())); + }).collect(Collectors.toList()); - Class memberClass = Class.forName(getClassName(memberType.toString())); - if (Property.class.isAssignableFrom(memberClass)) { - - elementList.add(e); - } - } - } catch (ClassNotFoundException ex) { - Exceptions.printStackTrace(ex); - } - } - return elementList; + return supportedFields; } catch (NullPointerException ex) { throw new CodeGeneratorException(ex); } From 2ac35c2430151c0c8ef7d71649a5a13ee11571e6 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sat, 22 Jul 2017 21:57:53 +0300 Subject: [PATCH 09/19] Fixed toUpperCase being locale sensitive. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For example, previously in the Turkish locale, property "idle" would generate a method "getİdle" instead of "getIdle". --- .../java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index c22b865..713f078 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -35,6 +35,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; @@ -282,7 +283,7 @@ private String getGetMethodName(String fieldName, String prefix) { private String prepareFieldNameForMethodName(String fieldName, boolean firstCharToUpperCase) { if (firstCharToUpperCase) { - fieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); + fieldName = fieldName.substring(0, 1).toUpperCase(Locale.ROOT) + fieldName.substring(1); } if (fieldName.endsWith(PROPERTY)) { From 99b4ff29a6efe261cd68878704799b5ca74077ee Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sat, 22 Jul 2017 23:55:16 +0300 Subject: [PATCH 10/19] Refactored code, no functional changes. --- .../netbeans/javafx/JavaFxBeanHelper.java | 24 +-- .../javafx/PropertyMethodBuilder.java | 169 ++++++++---------- .../{PackageHelper.java => TypeHelper.java} | 34 +++- 3 files changed, 116 insertions(+), 111 deletions(-) rename src/main/java/com/lynden/netbeans/javafx/{PackageHelper.java => TypeHelper.java} (71%) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index b441bb3..545fa46 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -24,7 +24,6 @@ package com.lynden.netbeans.javafx; import com.sun.source.tree.ClassTree; -import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import java.io.IOException; @@ -159,11 +158,12 @@ protected void generateCode(WorkingCopy wc, TreePath path, int position, List) classTree.getImplementsClause(), + classTree.getImplementsClause(), members); wc.rewrite(classTree, newClassTree); @@ -184,7 +184,7 @@ private List getFields(Lookup context, CompilationController co List allFields = ElementFilter.fieldsIn(elements.getAllMembers(typeElement)); List supportedFields = allFields.stream().filter((VariableElement var) -> { - return SUPPORTED_CLASSES.contains(getClassName(var.asType().toString())); + return SUPPORTED_CLASSES.contains(TypeHelper.getClassName(var.asType().toString())); }).collect(Collectors.toList()); return supportedFields; @@ -193,22 +193,6 @@ private List getFields(Lookup context, CompilationController co } } - public static String getClassName(String fullName) { - if (!fullName.contains("<")) { - return fullName; - } else { - return fullName.substring(0, fullName.indexOf('<')); - } - } - - public static String getTypeParameters(String fullName) { - if (!fullName.contains("<")) { - return ""; - } else { - return fullName.substring(fullName.indexOf('<') + 1, fullName.lastIndexOf('>')); - } - } - private static class CodeGeneratorException extends Exception { private static final long serialVersionUID = 1L; diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index 713f078..e84c880 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -24,9 +24,11 @@ package com.lynden.netbeans.javafx; import com.sun.source.tree.AnnotationTree; +import com.sun.source.tree.BlockTree; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.MethodTree; import com.sun.source.tree.ModifiersTree; +import com.sun.source.tree.StatementTree; import com.sun.source.tree.Tree; import com.sun.source.tree.TypeParameterTree; import com.sun.source.tree.VariableTree; @@ -66,8 +68,8 @@ public class PropertyMethodBuilder { private static String getValueType(String typeName) { - String className = JavaFxBeanHelper.getClassName(typeName); - String typeParams = JavaFxBeanHelper.getTypeParameters(typeName); + String className = TypeHelper.getClassName(typeName); + String typeParams = TypeHelper.getTypeParameters(typeName); if (VALUE_TYPES.containsKey(className)) { return VALUE_TYPES.get(className); @@ -85,22 +87,22 @@ private static String getValueType(String typeName) { private final TreeMaker make; private final List members; - private final List elements; + private final List fields; private final String className; public PropertyMethodBuilder(TreeMaker make, List members, - List elements, + List fields, String className) { this.make = make; this.members = members; - this.elements = elements; + this.fields = fields; this.className = className; } int removeExistingPropMethods(int index) { int counter = 0; - if (elements == null) { + if (fields == null) { return 0; } for (Iterator treeIt = members.iterator(); treeIt.hasNext();) { @@ -108,11 +110,11 @@ int removeExistingPropMethods(int index) { if (member.getKind().equals(Tree.Kind.METHOD)) { MethodTree mt = (MethodTree) member; - for (Element element : elements) { - if (mt.getName().contentEquals(getGetMethodName(element.getSimpleName().toString())) - || mt.getName().contentEquals(getGetMethodName(element.getSimpleName().toString(), "is")) - || mt.getName().contentEquals(getSetMethodName(element.getSimpleName().toString())) - || mt.getName().contentEquals(getPropertyMethodName(element.getSimpleName().toString()))) { + for (Element field : fields) { + if (mt.getName().contentEquals(getGetMethodName(field.getSimpleName().toString())) + || mt.getName().contentEquals(getGetMethodName(field.getSimpleName().toString(), "is")) + || mt.getName().contentEquals(getSetMethodName(field.getSimpleName().toString())) + || mt.getName().contentEquals(getPropertyMethodName(field.getSimpleName().toString()))) { treeIt.remove(); if (index > counter) { @@ -129,31 +131,45 @@ int removeExistingPropMethods(int index) { void addPropMethods(int index) { - if (elements == null) { + if (fields == null) { return; } int position = index - 1; - for (VariableElement element : elements) { + for (VariableElement field : fields) { position = Math.min(position + 1, members.size()); - members.add(position, createGetMethod(element)); + members.add(position, createGetMethod(field)); position = Math.min(position + 1, members.size()); - members.add(position, createSetMethod(element)); + members.add(position, createSetMethod(field)); position = Math.min(position + 1, members.size()); - members.add(position, createPropertyMethod(element)); + members.add(position, createPropertyMethod(field)); } } - protected MethodTree createGetMethod(VariableElement element) { + void addFields() { + for (VariableElement element : fields) { + VariableTree field + = make.Variable(make.Modifiers( + EnumSet.of(Modifier.PRIVATE), + Collections.emptyList()), + element.getSimpleName().toString(), + make.Identifier(toStringWithoutPackages(element)), + null); + + members.add(field); + } + } + + protected MethodTree createGetMethod(VariableElement field) { ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)); - String returnTypeName = getValueType(element.asType().toString()); + String returnTypeName = getValueType(field.asType().toString()); Tree returnType = make.Type(returnTypeName); String getterPrefix = ("boolean".equals(returnTypeName)) ? "is" : "get"; - String name = getGetMethodName(element.getSimpleName().toString(), getterPrefix); + String name = getGetMethodName(field.getSimpleName().toString(), getterPrefix); List typeParameters = Collections.emptyList(); @@ -161,7 +177,7 @@ protected MethodTree createGetMethod(VariableElement element) { List throwsList = Collections.emptyList(); - String body = createGetMethodBody(element); + BlockTree body = createGetMethodBody(field); ExpressionTree defaultValue = null; @@ -169,20 +185,23 @@ protected MethodTree createGetMethod(VariableElement element) { return make.Method(modifiers, name, returnType, typeParameters, parameters, throwsList, body, defaultValue); } - protected MethodTree createPropertyMethod(VariableElement element) { - ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC)); + protected MethodTree createSetMethod(VariableElement field) { + ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)); - Tree returnType = make.Type(element.asType().toString()); + Tree returnType = make.Type("void"); - String name = getPropertyMethodName(element.getSimpleName().toString()); + String name = getSetMethodName(field.getSimpleName().toString()); List typeParameters = Collections.emptyList(); - List parameters = Collections.emptyList(); + String parameterTypeName = getValueType(field.asType().toString()); + String parameterName = "value"; + VariableTree parameter = make.Variable(make.Modifiers(Collections.emptySet()), parameterName, make.Type(parameterTypeName), null); + List parameters = Collections.singletonList(parameter); List throwsList = Collections.emptyList(); - String body = createPropertyMethodBody(element); + BlockTree body = createSetMethodBody(field, parameterName); ExpressionTree defaultValue = null; @@ -190,22 +209,20 @@ protected MethodTree createPropertyMethod(VariableElement element) { return make.Method(modifiers, name, returnType, typeParameters, parameters, throwsList, body, defaultValue); } - protected MethodTree createSetMethod(VariableElement element) { - ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)); + protected MethodTree createPropertyMethod(VariableElement field) { + ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC)); - Tree returnType = make.Type("void"); + Tree returnType = make.Type(field.asType().toString()); - String name = getSetMethodName(element.getSimpleName().toString()); + String name = getPropertyMethodName(field.getSimpleName().toString()); List typeParameters = Collections.emptyList(); - String parameterTypeName = getValueType(element.asType().toString()); - VariableTree parameter = make.Variable(make.Modifiers(Collections.emptySet()), "value", make.Type(parameterTypeName), null); - List parameters = Collections.singletonList(parameter); + List parameters = Collections.emptyList(); List throwsList = Collections.emptyList(); - String body = createSetMethodBody(element); + BlockTree body = createPropertyMethodBody(field); ExpressionTree defaultValue = null; @@ -213,75 +230,47 @@ protected MethodTree createSetMethod(VariableElement element) { return make.Method(modifiers, name, returnType, typeParameters, parameters, throwsList, body, defaultValue); } - protected String createPropertyMethodBody(Element element) { - StringBuilder sb = new StringBuilder(); - sb.append("{\n") - .append("return ") - .append(element.getSimpleName()) - .append(";\n}"); - return sb.toString(); - } - - protected String createGetMethodBody(Element element) { - StringBuilder sb = new StringBuilder(); - sb.append("{\n") - .append("return ") - .append(element.getSimpleName()) - .append(".get();\n}"); - return sb.toString(); - } + protected BlockTree createGetMethodBody(VariableElement field) { + /* return field.get(); */ + ExpressionTree method = make.MemberSelect(make.Identifier(field), "get"); + StatementTree statement = make.Return(make.MethodInvocation(Collections.emptyList(), method, Collections.emptyList())); - protected String createSetMethodBody(Element element) { - StringBuilder sb = new StringBuilder(); - sb.append("{\n") - .append(element.getSimpleName()) - .append(".set(value);\n}"); - return sb.toString(); + return make.Block(Collections.singletonList(statement), false); } - void addFields() { - for (VariableElement element : elements) { - VariableTree field - = make.Variable(make.Modifiers( - EnumSet.of(Modifier.PRIVATE), - Collections.emptyList()), - element.getSimpleName().toString(), - make.Identifier(toStringWithoutPackages(element)), - null); + protected BlockTree createSetMethodBody(VariableElement field, String parameterName) { + /* field.set(parameterName); */ + ExpressionTree method = make.MemberSelect(make.Identifier(field), "set"); + ExpressionTree parameter = make.Identifier(parameterName); + StatementTree statement = make.ExpressionStatement(make.MethodInvocation(Collections.emptyList(), method, Collections.singletonList(parameter))); - members.add(field); - } + return make.Block(Collections.singletonList(statement), false); } - private String getPropertyMethodName(String fieldName) { - final StringBuilder sb = new StringBuilder(); - sb.append(this.prepareFieldNameForMethodName(fieldName, false)); - sb.append(PROPERTY); + protected BlockTree createPropertyMethodBody(VariableElement field) { + /* return field; */ + StatementTree statement = make.Return(make.Identifier(field)); - return sb.toString(); + return make.Block(Collections.singletonList(statement), false); } - private String getSetMethodName(String fieldName) { - final StringBuilder sb = new StringBuilder(); - sb.append("set"); - sb.append(this.prepareFieldNameForMethodName(fieldName)); - - return sb.toString(); + private static String getGetMethodName(String fieldName) { + return getGetMethodName(fieldName, "get"); } - private String getGetMethodName(String fieldName) { - return getGetMethodName(fieldName, "get"); + private static String getGetMethodName(String fieldName, String prefix) { + return prefix + prepareFieldNameForMethodName(fieldName); } - private String getGetMethodName(String fieldName, String prefix) { - final StringBuilder sb = new StringBuilder(); - sb.append(prefix); - sb.append(this.prepareFieldNameForMethodName(fieldName)); + private static String getSetMethodName(String fieldName) { + return "set" + prepareFieldNameForMethodName(fieldName); + } - return sb.toString(); + private static String getPropertyMethodName(String fieldName) { + return prepareFieldNameForMethodName(fieldName, false) + PROPERTY; } - private String prepareFieldNameForMethodName(String fieldName, boolean firstCharToUpperCase) { + private static String prepareFieldNameForMethodName(String fieldName, boolean firstCharToUpperCase) { if (firstCharToUpperCase) { fieldName = fieldName.substring(0, 1).toUpperCase(Locale.ROOT) + fieldName.substring(1); } @@ -293,12 +282,12 @@ private String prepareFieldNameForMethodName(String fieldName, boolean firstChar return fieldName; } - private String prepareFieldNameForMethodName(String fieldName) { - return this.prepareFieldNameForMethodName(fieldName, true); + private static String prepareFieldNameForMethodName(String fieldName) { + return prepareFieldNameForMethodName(fieldName, true); } private static String toStringWithoutPackages(VariableElement element) { - String fullProp = PackageHelper.removePackagesFromGenericsType(element.asType().toString()); + String fullProp = TypeHelper.removePackagesFromGenericsType(element.asType().toString()); return fullProp.substring(0, fullProp.indexOf(("Prop"))); } diff --git a/src/main/java/com/lynden/netbeans/javafx/PackageHelper.java b/src/main/java/com/lynden/netbeans/javafx/TypeHelper.java similarity index 71% rename from src/main/java/com/lynden/netbeans/javafx/PackageHelper.java rename to src/main/java/com/lynden/netbeans/javafx/TypeHelper.java index 2d943ad..0e2bac3 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PackageHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/TypeHelper.java @@ -30,7 +30,39 @@ * Manipulates strings containing types. * */ -class PackageHelper { +class TypeHelper { + + /** + * Returns only the class name part of a type name without type parameters. + * {@code "java.util.Map" -> "java.util.Map"} + * + * @param fullName + * @return class name + */ + static String getClassName(String fullName) { + if (!fullName.contains("<")) { + return fullName; + } else { + return fullName.substring(0, fullName.indexOf('<')); + } + } + + /** + * Returns only the type parameters part of a type name. Type params are in + * the same form as in the original type. If there were no type parameters, + * null is returned. + * {@code "java.util.Map" -> "java.lang.String, java.lang.String"} + * + * @param fullName + * @return type parameters + */ + static String getTypeParameters(String fullName) { + if (!fullName.contains("<")) { + return null; + } else { + return fullName.substring(fullName.indexOf('<') + 1, fullName.lastIndexOf('>')); + } + } /** Removes packages from class names (it manages generics too). i.e. * {@code java.lang.String -> String} and From 743d1bde68e9f120e4e2ce5b8bacc05227032734 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sun, 23 Jul 2017 00:16:58 +0300 Subject: [PATCH 11/19] Removed unused methods. --- .../netbeans/javafx/JavaFxBeanHelper.java | 10 ---- .../javafx/PropertyMethodBuilder.java | 22 --------- .../lynden/netbeans/javafx/TypeHelper.java | 46 ------------------- 3 files changed, 78 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index 545fa46..8640760 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -74,16 +74,6 @@ public class JavaFxBeanHelper implements CodeGenerator { protected JFXPanel panel = new JFXPanel(); protected List fields; - public JavaFxBeanHelper textComponent(final JTextComponent value) { - this.textComponent = value; - return this; - } - - public JavaFxBeanHelper fields(final List value) { - this.fields = value; - return this; - } - /** * * @param context containing JTextComponent and possibly other items diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index e84c880..a9bfc89 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -23,7 +23,6 @@ */ package com.lynden.netbeans.javafx; -import com.sun.source.tree.AnnotationTree; import com.sun.source.tree.BlockTree; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.MethodTree; @@ -148,20 +147,6 @@ void addPropMethods(int index) { } } - void addFields() { - for (VariableElement element : fields) { - VariableTree field - = make.Variable(make.Modifiers( - EnumSet.of(Modifier.PRIVATE), - Collections.emptyList()), - element.getSimpleName().toString(), - make.Identifier(toStringWithoutPackages(element)), - null); - - members.add(field); - } - } - protected MethodTree createGetMethod(VariableElement field) { ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC, Modifier.FINAL)); @@ -285,11 +270,4 @@ private static String prepareFieldNameForMethodName(String fieldName, boolean fi private static String prepareFieldNameForMethodName(String fieldName) { return prepareFieldNameForMethodName(fieldName, true); } - - private static String toStringWithoutPackages(VariableElement element) { - String fullProp = TypeHelper.removePackagesFromGenericsType(element.asType().toString()); - - return fullProp.substring(0, fullProp.indexOf(("Prop"))); - } - } diff --git a/src/main/java/com/lynden/netbeans/javafx/TypeHelper.java b/src/main/java/com/lynden/netbeans/javafx/TypeHelper.java index 0e2bac3..3dd43d2 100644 --- a/src/main/java/com/lynden/netbeans/javafx/TypeHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/TypeHelper.java @@ -23,9 +23,6 @@ */ package com.lynden.netbeans.javafx; -import java.util.ArrayList; -import java.util.List; - /** * Manipulates strings containing types. * @@ -63,47 +60,4 @@ static String getTypeParameters(String fullName) { return fullName.substring(fullName.indexOf('<') + 1, fullName.lastIndexOf('>')); } } - - /** Removes packages from class names (it manages generics too). i.e. - * {@code java.lang.String -> String} and - * {@code java.util.List -> List}. - */ - static String removePackagesFromGenericsType(String fullName) { - final List list = new ArrayList<>(); - int idx = 0, counter = 0; - for (char c : fullName.toCharArray()) { - switch (c) { - case ',': - case '<': - case '>': - list.add(fullName.substring(idx, counter)); - list.add(String.valueOf(c)); - idx = counter + 1; - break; - } - counter++; - } - if (list.isEmpty()) { - return removePackageFromType(fullName); - } - StringBuilder buf = new StringBuilder(); - for (String s : list) { - if ("<>,".contains(s)) { - buf.append(s); - } else { - buf.append(removePackageFromType(s)); - } - } - return buf.toString(); - } - - /** Removes the package from a single class name (don't manage generics). */ - static String removePackageFromType(String fullname) { - int lastIndexOfPoint = fullname.lastIndexOf('.'); - if (lastIndexOfPoint == -1) { - return fullname; - } - return fullname.substring(lastIndexOfPoint + 1, fullname.length()); - } - } From 772c1c65cd37fe0890fcffd955fe2f731d423167 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sun, 23 Jul 2017 19:38:19 +0300 Subject: [PATCH 12/19] Old methods no longer get removed at generation. Instead, new methods check if there is already a method with the same name. If there is, the new method just won't get created. This ensures that no code will be accidentally removed. This is also how the NetBeans default "Getter and Setter..." generator works. --- .../netbeans/javafx/JavaFxBeanHelper.java | 15 +++-- .../javafx/PropertyMethodBuilder.java | 57 +++---------------- .../lynden/netbeans/javafx/TreeHelper.java | 15 +++++ 3 files changed, 34 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index 8640760..253e221 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -24,6 +24,7 @@ package com.lynden.netbeans.javafx; import com.sun.source.tree.ClassTree; +import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import java.io.IOException; @@ -135,18 +136,22 @@ protected void generateCode(WorkingCopy wc, TreePath path, int position, List members = new ArrayList<>(classTree.getMembers()); - String className = typeClassElement.toString(); - PropertyMethodBuilder propertyMethodBuilder = new PropertyMethodBuilder(make, members, fields, className); + PropertyMethodBuilder propertyMethodBuilder = new PropertyMethodBuilder(make, fields); - index = propertyMethodBuilder.removeExistingPropMethods(index); + List createdMethods = propertyMethodBuilder.createPropMethods(); - propertyMethodBuilder.addPropMethods(index); + /* Filtering out methods that might clash with the pre-existing + * ones. */ + createdMethods.removeIf((MethodTree createdMethod) -> { + return TreeHelper.hasMethodWithSameName(members, createdMethod); + }); + + members.addAll(position, createdMethods); ClassTree newClassTree = make.Class( classTree.getModifiers(), diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index a9bfc89..0fd162b 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -31,14 +31,13 @@ import com.sun.source.tree.Tree; import com.sun.source.tree.TypeParameterTree; import com.sun.source.tree.VariableTree; +import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; import org.netbeans.api.java.source.TreeMaker; @@ -85,66 +84,28 @@ private static String getValueType(String typeName) { } private final TreeMaker make; - private final List members; private final List fields; - private final String className; - public PropertyMethodBuilder(TreeMaker make, - List members, - List fields, - String className) { + public PropertyMethodBuilder(TreeMaker make, List fields) { this.make = make; - this.members = members; this.fields = fields; - this.className = className; } - int removeExistingPropMethods(int index) { - int counter = 0; - if (fields == null) { - return 0; - } - for (Iterator treeIt = members.iterator(); treeIt.hasNext();) { - Tree member = treeIt.next(); - - if (member.getKind().equals(Tree.Kind.METHOD)) { - MethodTree mt = (MethodTree) member; - for (Element field : fields) { - if (mt.getName().contentEquals(getGetMethodName(field.getSimpleName().toString())) - || mt.getName().contentEquals(getGetMethodName(field.getSimpleName().toString(), "is")) - || mt.getName().contentEquals(getSetMethodName(field.getSimpleName().toString())) - || mt.getName().contentEquals(getPropertyMethodName(field.getSimpleName().toString()))) { - - treeIt.remove(); - if (index > counter) { - index--; - } - break; - } - } - } - counter++; - } - return index; - } - - void addPropMethods(int index) { + List createPropMethods() { if (fields == null) { - return; + return Collections.emptyList(); } - int position = index - 1; + List createdMethods = new ArrayList<>(); for (VariableElement field : fields) { - position = Math.min(position + 1, members.size()); - members.add(position, createGetMethod(field)); - position = Math.min(position + 1, members.size()); - members.add(position, createSetMethod(field)); - position = Math.min(position + 1, members.size()); - members.add(position, createPropertyMethod(field)); + createdMethods.add(createGetMethod(field)); + createdMethods.add(createSetMethod(field)); + createdMethods.add(createPropertyMethod(field)); } + return createdMethods; } protected MethodTree createGetMethod(VariableElement field) { diff --git a/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java b/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java index d723ec2..e58f97b 100644 --- a/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java @@ -24,10 +24,12 @@ package com.lynden.netbeans.javafx; import com.sun.source.tree.ClassTree; +import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; import com.sun.source.util.SourcePositions; import com.sun.source.util.TreePath; import java.io.IOException; +import java.util.Collection; import javax.swing.text.Document; import org.netbeans.api.java.source.WorkingCopy; import org.netbeans.editor.GuardedDocument; @@ -100,4 +102,17 @@ static int findClassMemberIndex(WorkingCopy wc, return index; } + /** + * Checks if the given collection of {@code members} contains a method with + * the same name as the given {@code method}. + * + * @param members + * @param method + * @return true if the collection contains a method with the same name + */ + static boolean hasMethodWithSameName(Collection members, MethodTree method) { + return members.stream().anyMatch((Tree member) -> { + return member.getKind().equals(Tree.Kind.METHOD) && ((MethodTree) member).getName().contentEquals(method.getName()); + }); + } } From 78de253b7b85fa319118f8c3bf93e191a68851b8 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Sun, 23 Jul 2017 20:29:51 +0300 Subject: [PATCH 13/19] Added support for read-only properties. --- .../netbeans/javafx/JavaFxBeanHelper.java | 11 +++++ .../javafx/PropertyMethodBuilder.java | 47 +++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index 253e221..b668ab9 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -68,6 +68,17 @@ public class JavaFxBeanHelper implements CodeGenerator { SUPPORTED_CLASSES.add("javafx.beans.property.SetProperty"); SUPPORTED_CLASSES.add("javafx.beans.property.MapProperty"); SUPPORTED_CLASSES.add("javafx.beans.property.ObjectProperty"); + + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyIntegerProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyLongProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyFloatProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyDoubleProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyBooleanProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyStringProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyListProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlySetProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyMapProperty"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyObjectProperty"); } protected JTextComponent textComponent; diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index 0fd162b..a886419 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -35,9 +35,11 @@ import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; import org.netbeans.api.java.source.TreeMaker; @@ -48,20 +50,54 @@ public class PropertyMethodBuilder { private static final String PROPERTY = "Property"; // NOI18N + private static final Map VALUE_TYPES = new HashMap<>(); private static final Map GENERIC_VALUE_TYPES = new HashMap<>(); + private static final Set VALUE_TYPE_AS_PARAM = new HashSet<>(); + + private static final Set WRITABLE_PROPERTIES = new HashSet<>(); static { + + /* Type of the value can be found in map. */ VALUE_TYPES.put("javafx.beans.property.IntegerProperty", "int"); VALUE_TYPES.put("javafx.beans.property.LongProperty", "long"); VALUE_TYPES.put("javafx.beans.property.FloatProperty", "float"); VALUE_TYPES.put("javafx.beans.property.DoubleProperty", "double"); VALUE_TYPES.put("javafx.beans.property.BooleanProperty", "boolean"); VALUE_TYPES.put("javafx.beans.property.StringProperty", "java.lang.String"); - + VALUE_TYPES.put("javafx.beans.property.ReadOnlyIntegerProperty", "int"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyLongProperty", "long"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyFloatProperty", "float"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyDoubleProperty", "double"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyBooleanProperty", "boolean"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyStringProperty", "java.lang.String"); + + /* Type of the value can be found in map, but it requires the same type + * parameters as the property type. */ GENERIC_VALUE_TYPES.put("javafx.beans.property.ListProperty", "javafx.collections.ObservableList"); GENERIC_VALUE_TYPES.put("javafx.beans.property.SetProperty", "javafx.collections.ObservableSet"); GENERIC_VALUE_TYPES.put("javafx.beans.property.MapProperty", "javafx.collections.ObservableMap"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlyListProperty", "javafx.collections.ObservableList"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlySetProperty", "javafx.collections.ObservableSet"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlyMapProperty", "javafx.collections.ObservableMap"); + + /* Type of the value is given as a type parameter of the property type. */ + VALUE_TYPE_AS_PARAM.add("javafx.beans.property.ObjectProperty"); + VALUE_TYPE_AS_PARAM.add("javafx.beans.property.ReadOnlyObjectProperty"); + + + /* These property types are writable. */ + WRITABLE_PROPERTIES.add("javafx.beans.property.IntegerProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.LongProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.FloatProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.DoubleProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.BooleanProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.StringProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.ListProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.SetProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.MapProperty"); + WRITABLE_PROPERTIES.add("javafx.beans.property.ObjectProperty"); } private static String getValueType(String typeName) { @@ -75,7 +111,7 @@ private static String getValueType(String typeName) { } else if (GENERIC_VALUE_TYPES.containsKey(className)) { return GENERIC_VALUE_TYPES.get(className) + '<' + typeParams + '>'; - } else if (className.equals("javafx.beans.property.ObjectProperty")) { + } else if (VALUE_TYPE_AS_PARAM.contains(className)) { return typeParams; } else { @@ -101,7 +137,12 @@ List createPropMethods() { for (VariableElement field : fields) { createdMethods.add(createGetMethod(field)); - createdMethods.add(createSetMethod(field)); + + /* Only create set method if property is writable */ + if (WRITABLE_PROPERTIES.contains(TypeHelper.getClassName(field.asType().toString()))) { + createdMethods.add(createSetMethod(field)); + } + createdMethods.add(createPropertyMethod(field)); } From 0c8663ff9d68e9b4d41100cf8aba08ca50019dbe Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Mon, 24 Jul 2017 01:04:32 +0300 Subject: [PATCH 14/19] Added support for read-only wrappers. --- .../netbeans/javafx/JavaFxBeanHelper.java | 11 ++++ .../javafx/PropertyMethodBuilder.java | 66 +++++++++++++++++-- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index b668ab9..2bbf7d2 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -79,6 +79,17 @@ public class JavaFxBeanHelper implements CodeGenerator { SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlySetProperty"); SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyMapProperty"); SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyObjectProperty"); + + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyIntegerWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyLongWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyFloatWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyDoubleWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyBooleanWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyStringWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyListWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlySetWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyMapWrapper"); + SUPPORTED_CLASSES.add("javafx.beans.property.ReadOnlyObjectWrapper"); } protected JTextComponent textComponent; diff --git a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java index a886419..e93f54b 100644 --- a/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java +++ b/src/main/java/com/lynden/netbeans/javafx/PropertyMethodBuilder.java @@ -56,6 +56,7 @@ public class PropertyMethodBuilder { private static final Set VALUE_TYPE_AS_PARAM = new HashSet<>(); private static final Set WRITABLE_PROPERTIES = new HashSet<>(); + private static final Map WRAPPED_READ_ONLY_TYPES = new HashMap<>(); static { @@ -72,6 +73,12 @@ public class PropertyMethodBuilder { VALUE_TYPES.put("javafx.beans.property.ReadOnlyDoubleProperty", "double"); VALUE_TYPES.put("javafx.beans.property.ReadOnlyBooleanProperty", "boolean"); VALUE_TYPES.put("javafx.beans.property.ReadOnlyStringProperty", "java.lang.String"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyIntegerWrapper", "int"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyLongWrapper", "long"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyFloatWrapper", "float"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyDoubleWrapper", "double"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyBooleanWrapper", "boolean"); + VALUE_TYPES.put("javafx.beans.property.ReadOnlyStringWrapper", "java.lang.String"); /* Type of the value can be found in map, but it requires the same type * parameters as the property type. */ @@ -81,10 +88,14 @@ public class PropertyMethodBuilder { GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlyListProperty", "javafx.collections.ObservableList"); GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlySetProperty", "javafx.collections.ObservableSet"); GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlyMapProperty", "javafx.collections.ObservableMap"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlyListWrapper", "javafx.collections.ObservableList"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlySetWrapper", "javafx.collections.ObservableSet"); + GENERIC_VALUE_TYPES.put("javafx.beans.property.ReadOnlyMapWrapper", "javafx.collections.ObservableMap"); /* Type of the value is given as a type parameter of the property type. */ VALUE_TYPE_AS_PARAM.add("javafx.beans.property.ObjectProperty"); VALUE_TYPE_AS_PARAM.add("javafx.beans.property.ReadOnlyObjectProperty"); + VALUE_TYPE_AS_PARAM.add("javafx.beans.property.ReadOnlyObjectWrapper"); /* These property types are writable. */ @@ -98,6 +109,19 @@ public class PropertyMethodBuilder { WRITABLE_PROPERTIES.add("javafx.beans.property.SetProperty"); WRITABLE_PROPERTIES.add("javafx.beans.property.MapProperty"); WRITABLE_PROPERTIES.add("javafx.beans.property.ObjectProperty"); + + /* Read-only wrapper types and their respective wrapped types. These may + * or may not be generic. If they are, the type parameters are the same. */ + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyIntegerWrapper", "javafx.beans.property.ReadOnlyIntegerProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyLongWrapper", "javafx.beans.property.ReadOnlyLongProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyFloatWrapper", "javafx.beans.property.ReadOnlyFloatProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyDoubleWrapper", "javafx.beans.property.ReadOnlyDoubleProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyBooleanWrapper", "javafx.beans.property.ReadOnlyBooleanProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyStringWrapper", "javafx.beans.property.ReadOnlyStringProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyListWrapper", "javafx.beans.property.ReadOnlyListProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlySetWrapper", "javafx.beans.property.ReadOnlySetProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyMapWrapper", "javafx.beans.property.ReadOnlyMapProperty"); + WRAPPED_READ_ONLY_TYPES.put("javafx.beans.property.ReadOnlyObjectWrapper", "javafx.beans.property.ReadOnlyObjectProperty"); } private static String getValueType(String typeName) { @@ -119,6 +143,26 @@ private static String getValueType(String typeName) { } } + private static boolean isWritableType(String typeName) { + return WRITABLE_PROPERTIES.contains(TypeHelper.getClassName(typeName)); + } + + private static boolean isWrapperType(String typeName) { + return WRAPPED_READ_ONLY_TYPES.containsKey(TypeHelper.getClassName(typeName)); + } + + private static String getWrappedReadOnlyType(String typeName) { + + String className = TypeHelper.getClassName(typeName); + String typeParams = TypeHelper.getTypeParameters(typeName); + + if (typeParams == null) { + return WRAPPED_READ_ONLY_TYPES.get(className); + } else { + return WRAPPED_READ_ONLY_TYPES.get(className) + '<' + typeParams + '>'; + } + } + private final TreeMaker make; private final List fields; @@ -139,7 +183,7 @@ List createPropMethods() { createdMethods.add(createGetMethod(field)); /* Only create set method if property is writable */ - if (WRITABLE_PROPERTIES.contains(TypeHelper.getClassName(field.asType().toString()))) { + if (isWritableType(field.asType().toString())) { createdMethods.add(createSetMethod(field)); } @@ -199,7 +243,10 @@ protected MethodTree createSetMethod(VariableElement field) { protected MethodTree createPropertyMethod(VariableElement field) { ModifiersTree modifiers = make.Modifiers(EnumSet.of(Modifier.PUBLIC)); - Tree returnType = make.Type(field.asType().toString()); + String fieldTypeName = field.asType().toString(); + boolean isReadOnlyWrapper = isWrapperType(fieldTypeName); + + Tree returnType = make.Type(isReadOnlyWrapper ? getWrappedReadOnlyType(fieldTypeName) : fieldTypeName); String name = getPropertyMethodName(field.getSimpleName().toString()); @@ -209,7 +256,7 @@ protected MethodTree createPropertyMethod(VariableElement field) { List throwsList = Collections.emptyList(); - BlockTree body = createPropertyMethodBody(field); + BlockTree body = createPropertyMethodBody(field, isReadOnlyWrapper); ExpressionTree defaultValue = null; @@ -234,9 +281,16 @@ protected BlockTree createSetMethodBody(VariableElement field, String parameterN return make.Block(Collections.singletonList(statement), false); } - protected BlockTree createPropertyMethodBody(VariableElement field) { - /* return field; */ - StatementTree statement = make.Return(make.Identifier(field)); + protected BlockTree createPropertyMethodBody(VariableElement field, boolean isReadOnlyWrapper) { + StatementTree statement; + if (isReadOnlyWrapper) { + /* return field.getReadOnlyProperty(); */ + ExpressionTree method = make.MemberSelect(make.Identifier(field), "getReadOnlyProperty"); + statement = make.Return(make.MethodInvocation(Collections.emptyList(), method, Collections.emptyList())); + } else { + /* return field; */ + statement = make.Return(make.Identifier(field)); + } return make.Block(Collections.singletonList(statement), false); } From 0164efa3fb74e23ec43cd79a85dda52910ef1153 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Mon, 24 Jul 2017 20:01:51 +0300 Subject: [PATCH 15/19] Fixed generation not working in enum classes. Uses a new method TreeUtilities.getPathElementOfKind, which was added in NetBeans 8.1. For this reason, all NetBeans dependencies are updated to 8.1. --- pom.xml | 25 +++++++++++-------- .../javafx/CodeGeneratorCancellableTask.java | 8 ++++-- .../netbeans/javafx/JavaFxBeanHelper.java | 3 ++- .../lynden/netbeans/javafx/TreeHelper.java | 21 ---------------- 4 files changed, 23 insertions(+), 34 deletions(-) diff --git a/pom.xml b/pom.xml index be46058..12db3d5 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ Rob Terpilowski MIT License LICENSE - mykeystore + mykeystore myself @@ -61,47 +61,52 @@ org.netbeans.api org-netbeans-api-annotations-common - RELEASE802 + RELEASE81 org.netbeans.api org-netbeans-modules-editor-lib2 - RELEASE802 + RELEASE81 org.netbeans.api org-netbeans-modules-editor-mimelookup - RELEASE802 + RELEASE81 org.netbeans.api org-openide-util-lookup - RELEASE802 + RELEASE81 org.netbeans.api org-netbeans-libs-javacapi - RELEASE802 + RELEASE81 org.netbeans.api org-netbeans-modules-java-source - RELEASE802 + RELEASE81 org.netbeans.api org-openide-util - RELEASE802 + RELEASE81 org.netbeans.api org-netbeans-modules-editor-lib - RELEASE802 + RELEASE81 org.netbeans.api org-netbeans-libs-javafx - RELEASE802 + RELEASE81 + + + org.netbeans.api + org-netbeans-modules-java-source-base + RELEASE81 diff --git a/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java b/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java index 1d9c1f8..8061ba6 100644 --- a/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java +++ b/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java @@ -27,9 +27,11 @@ import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import java.io.IOException; +import java.util.EnumSet; import javax.swing.text.JTextComponent; import org.netbeans.api.java.source.CancellableTask; import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.java.source.TreeUtilities; import org.netbeans.api.java.source.WorkingCopy; /** @@ -55,9 +57,11 @@ public abstract void generateCode(WorkingCopy workingCopy, TreePath path, int position); private void generate(WorkingCopy wc) throws IOException { + TreeUtilities treeUtils = wc.getTreeUtilities(); + final int caretOffset = textComponent.getCaretPosition(); - TreePath path = wc.getTreeUtilities().pathFor(caretOffset); - path = TreeHelper.getParentElementOfKind(Tree.Kind.CLASS, path); + TreePath path = treeUtils.pathFor(caretOffset); + path = treeUtils.getPathElementOfKind(EnumSet.of(Tree.Kind.CLASS, Tree.Kind.ENUM), path); int idx = TreeHelper.findClassMemberIndex(wc, (ClassTree) path.getLeaf(), caretOffset); generateCode(wc, path, idx); } diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index 2bbf7d2..b86b178 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -190,7 +191,7 @@ protected void generateCode(WorkingCopy wc, TreePath path, int position, List getFields(Lookup context, CompilationController controller) throws CodeGeneratorException { try { TreePath treePath = context.lookup(TreePath.class); - TreePath path = TreeHelper.getParentElementOfKind(Tree.Kind.CLASS, treePath); + TreePath path = controller.getTreeUtilities().getPathElementOfKind(EnumSet.of(Tree.Kind.CLASS, Tree.Kind.ENUM), treePath); TypeElement typeElement = (TypeElement) controller.getTrees().getElement(path); if (!typeElement.getKind().isClass()) { diff --git a/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java b/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java index e58f97b..0d252e9 100644 --- a/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/TreeHelper.java @@ -27,7 +27,6 @@ import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; import com.sun.source.util.SourcePositions; -import com.sun.source.util.TreePath; import java.io.IOException; import java.util.Collection; import javax.swing.text.Document; @@ -39,26 +38,6 @@ */ class TreeHelper { - /** - * Search up the hierarchy of elements for one of the given kind. - * - * @param kind the element's kind to search for - * @param path the starting element - * @return {@code null} if no element was found. - */ - static TreePath getParentElementOfKind(Tree.Kind kind, TreePath path) { - if (path != null) { - TreePath tpath = path; - while (tpath != null) { - if (kind == tpath.getLeaf().getKind()) { - return tpath; - } - tpath = tpath.getParentPath(); - } - } - return null; - } - /** * Find the index of the current class member. * From edc858d5e53f8fb801973ae06c67686a6f15df6a Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Mon, 24 Jul 2017 20:19:10 +0300 Subject: [PATCH 16/19] Fixed NullPointer when opening "Generate code" dialog outside of a class. --- .../lynden/netbeans/javafx/JavaFxBeanHelper.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index b86b178..1840d81 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -48,6 +48,7 @@ import org.netbeans.api.java.source.JavaSource; import org.netbeans.api.java.source.ModificationResult; import org.netbeans.api.java.source.TreeMaker; +import org.netbeans.api.java.source.TreeUtilities; import org.netbeans.api.java.source.WorkingCopy; import org.netbeans.spi.editor.codegen.CodeGenerator; import org.netbeans.spi.editor.codegen.CodeGeneratorContextProvider; @@ -118,7 +119,17 @@ public static class Factory implements CodeGenerator.Factory { @Override public List create(Lookup context) { - return Collections.singletonList(new JavaFxBeanHelper(context)); + CompilationController controller = context.lookup(CompilationController.class); + TreePath path = context.lookup(TreePath.class); + + TreeUtilities treeUtils = controller.getTreeUtilities(); + + TreePath classTreePath = treeUtils.getPathElementOfKind(EnumSet.of(Tree.Kind.CLASS, Tree.Kind.ENUM), path); + if (classTreePath != null) { + return Collections.singletonList(new JavaFxBeanHelper(context)); + } else { + return Collections.emptyList(); + } } } From 76c4a11ab0a10057ba8705df5e60c2e87d9849cc Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Mon, 24 Jul 2017 22:34:26 +0300 Subject: [PATCH 17/19] Refactored code, no functional changes. --- .../javafx/CodeGeneratorCancellableTask.java | 16 +-- .../netbeans/javafx/JavaFxBeanHelper.java | 101 +++++++----------- 2 files changed, 46 insertions(+), 71 deletions(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java b/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java index 8061ba6..65723b7 100644 --- a/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java +++ b/src/main/java/com/lynden/netbeans/javafx/CodeGeneratorCancellableTask.java @@ -23,11 +23,8 @@ */ package com.lynden.netbeans.javafx; -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import java.io.IOException; -import java.util.EnumSet; import javax.swing.text.JTextComponent; import org.netbeans.api.java.source.CancellableTask; import org.netbeans.api.java.source.JavaSource; @@ -53,19 +50,16 @@ public void run(WorkingCopy workingCopy) throws IOException { generate(workingCopy); } - public abstract void generateCode(WorkingCopy workingCopy, TreePath path, - int position); - private void generate(WorkingCopy wc) throws IOException { TreeUtilities treeUtils = wc.getTreeUtilities(); - final int caretOffset = textComponent.getCaretPosition(); - TreePath path = treeUtils.pathFor(caretOffset); - path = treeUtils.getPathElementOfKind(EnumSet.of(Tree.Kind.CLASS, Tree.Kind.ENUM), path); - int idx = TreeHelper.findClassMemberIndex(wc, (ClassTree) path.getLeaf(), caretOffset); - generateCode(wc, path, idx); + int caretPosition = textComponent.getCaretPosition(); + TreePath treePathAtCaret = treeUtils.pathFor(caretPosition); + generateCode(wc, treePathAtCaret, caretPosition); } + protected abstract void generateCode(WorkingCopy workingCopy, TreePath treePathAtCaret, int caretPosition); + @Override public void cancel() { } diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index 1840d81..f77ed02 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -27,6 +27,7 @@ import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; +import com.sun.source.util.Trees; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -97,7 +98,6 @@ public class JavaFxBeanHelper implements CodeGenerator { protected JTextComponent textComponent; //this is needed to initialize the JavaFx Toolkit protected JFXPanel panel = new JFXPanel(); - protected List fields; /** * @@ -106,12 +106,6 @@ public class JavaFxBeanHelper implements CodeGenerator { */ private JavaFxBeanHelper(Lookup context) { // Good practice is not to save Lookup outside ctor textComponent = context.lookup(JTextComponent.class); - CompilationController controller = context.lookup(CompilationController.class); - try { - fields = getFields(context, controller); - } catch (CodeGeneratorException ex) { - Exceptions.printStackTrace(ex); - } } @MimeRegistration(mimeType = "text/x-java", position = 250, service = CodeGenerator.Factory.class) @@ -152,8 +146,8 @@ public void invoke() { CancellableTask task = new CodeGeneratorCancellableTask(textComponent) { @Override - public void generateCode(WorkingCopy workingCopy, TreePath path, int position) { - JavaFxBeanHelper.this.generateCode(workingCopy, path, position, JavaFxBeanHelper.this.fields); + protected void generateCode(WorkingCopy workingCopy, TreePath treePathAtCaret, int caretPosition) { + JavaFxBeanHelper.this.generateCode(workingCopy, treePathAtCaret, caretPosition); } }; @@ -166,73 +160,60 @@ public void generateCode(WorkingCopy workingCopy, TreePath path, int position) { } - protected void generateCode(WorkingCopy wc, TreePath path, int position, List fields) { + protected void generateCode(WorkingCopy wc, TreePath treePathAtCaret, int caretPosition) { + TreeUtilities treeUtils = wc.getTreeUtilities(); - TypeElement typeClassElement = (TypeElement) wc.getTrees().getElement(path); - if (typeClassElement != null) { + TreePath classTreePath = treeUtils.getPathElementOfKind(EnumSet.of(Tree.Kind.CLASS, Tree.Kind.ENUM), treePathAtCaret); + if (classTreePath != null) { - TreeMaker make = wc.getTreeMaker(); - ClassTree classTree = (ClassTree) path.getLeaf(); - List members = new ArrayList<>(classTree.getMembers()); + int classMemberIndexAtCaret = TreeHelper.findClassMemberIndex(wc, (ClassTree) classTreePath.getLeaf(), caretPosition); - PropertyMethodBuilder propertyMethodBuilder = new PropertyMethodBuilder(make, fields); + generateCodeInClass(wc, classTreePath, classMemberIndexAtCaret); + } + } - List createdMethods = propertyMethodBuilder.createPropMethods(); + protected void generateCodeInClass(WorkingCopy wc, TreePath classTreePath, int classMemberIndexAtCaret) { - /* Filtering out methods that might clash with the pre-existing - * ones. */ - createdMethods.removeIf((MethodTree createdMethod) -> { - return TreeHelper.hasMethodWithSameName(members, createdMethod); - }); + List fields = getFields(wc, classTreePath); - members.addAll(position, createdMethods); + TreeMaker make = wc.getTreeMaker(); + ClassTree classTree = (ClassTree) classTreePath.getLeaf(); + List members = new ArrayList<>(classTree.getMembers()); - ClassTree newClassTree = make.Class( - classTree.getModifiers(), - classTree.getSimpleName(), - classTree.getTypeParameters(), - classTree.getExtendsClause(), - classTree.getImplementsClause(), - members); + PropertyMethodBuilder propertyMethodBuilder = new PropertyMethodBuilder(make, fields); - wc.rewrite(classTree, newClassTree); - } - } + List createdMethods = propertyMethodBuilder.createPropMethods(); - private List getFields(Lookup context, CompilationController controller) throws CodeGeneratorException { - try { - TreePath treePath = context.lookup(TreePath.class); - TreePath path = controller.getTreeUtilities().getPathElementOfKind(EnumSet.of(Tree.Kind.CLASS, Tree.Kind.ENUM), treePath); - TypeElement typeElement = (TypeElement) controller.getTrees().getElement(path); + /* Filtering out methods that might clash with the pre-existing ones. */ + createdMethods.removeIf((MethodTree createdMethod) -> { + return TreeHelper.hasMethodWithSameName(members, createdMethod); + }); - if (!typeElement.getKind().isClass()) { - throw new CodeGeneratorException("typeElement " + typeElement.getKind().name() + " is not a class, cannot generate code."); - } - - Elements elements = controller.getElements(); - List allFields = ElementFilter.fieldsIn(elements.getAllMembers(typeElement)); + members.addAll(classMemberIndexAtCaret, createdMethods); - List supportedFields = allFields.stream().filter((VariableElement var) -> { - return SUPPORTED_CLASSES.contains(TypeHelper.getClassName(var.asType().toString())); - }).collect(Collectors.toList()); + ClassTree newClassTree = make.Class( + classTree.getModifiers(), + classTree.getSimpleName(), + classTree.getTypeParameters(), + classTree.getExtendsClause(), + classTree.getImplementsClause(), + members); - return supportedFields; - } catch (NullPointerException ex) { - throw new CodeGeneratorException(ex); - } + wc.rewrite(classTree, newClassTree); } - private static class CodeGeneratorException extends Exception { + private static List getFields(CompilationController controller, TreePath classTreePath) { + Trees trees = controller.getTrees(); + Elements elements = controller.getElements(); - private static final long serialVersionUID = 1L; + TypeElement typeElement = (TypeElement) trees.getElement(classTreePath); - public CodeGeneratorException(String message) { - super(message); - } + List allFields = ElementFilter.fieldsIn(elements.getAllMembers(typeElement)); - public CodeGeneratorException(Throwable cause) { - super(cause); - } - } + List supportedFields = allFields.stream().filter((VariableElement var) -> { + return SUPPORTED_CLASSES.contains(TypeHelper.getClassName(var.asType().toString())); + }).collect(Collectors.toList()); + return supportedFields; + } } From 1ae18d5ed618ae36265cdafb1ec901945ddfbbf2 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Mon, 24 Jul 2017 22:47:17 +0300 Subject: [PATCH 18/19] Generator now appears only if class has property fields. --- .../java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java index f77ed02..ccd9d6c 100644 --- a/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java +++ b/src/main/java/com/lynden/netbeans/javafx/JavaFxBeanHelper.java @@ -119,7 +119,10 @@ public List create(Lookup context) { TreeUtilities treeUtils = controller.getTreeUtilities(); TreePath classTreePath = treeUtils.getPathElementOfKind(EnumSet.of(Tree.Kind.CLASS, Tree.Kind.ENUM), path); - if (classTreePath != null) { + + /* Are we in a class and does the class have supported property + * fields? */ + if ((classTreePath != null) && (!getFields(controller, classTreePath).isEmpty())) { return Collections.singletonList(new JavaFxBeanHelper(context)); } else { return Collections.emptyList(); From f3f027412e3b27ecfaeb1f178a854e1150a74a99 Mon Sep 17 00:00:00 2001 From: Tuupertunut Date: Tue, 25 Jul 2017 01:25:38 +0300 Subject: [PATCH 19/19] Updated readme. --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e971be6..971d026 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ private StringProperty name; public StringProperty getName() { return name; } -public void setName( StringProperty name ) { + +public void setName(StringProperty name) { this.name = name; } ``` @@ -24,11 +25,11 @@ public final String getName() { return name.get(); } -public final void setName( String value ) { +public final void setName(String value) { name.set(value); } -public final StringProperty nameProperty() { +public StringProperty nameProperty() { return name; } ``` @@ -38,19 +39,46 @@ which will create the following methods: ```java private StringProperty nameProperty; + public final String getName() { return nameProperty.get(); } -public final void setName( String value ) { +public final void setName(String value) { nameProperty.set(value); } -public final StringProperty nameProperty() { +public StringProperty nameProperty() { return nameProperty; } ``` +Read-only properties and read-only wrapper types are also supported: + +```java +private ReadOnlyStringProperty identifier; + +public final String getIdentifier() { + return identifier.get(); +} + +public ReadOnlyStringProperty identifierProperty() { + return identifier; +} +``` + +```java +private ReadOnlyStringWrapper identifier; + +public final String getIdentifier() { + return identifier.get(); +} + +public ReadOnlyStringProperty identifierProperty() { + return identifier.getReadOnlyProperty(); +} +``` + # Usage @@ -71,12 +99,35 @@ Methods for supported property types will automatically be generated. * FloatProperty * IntegerProperty * LongProperty - - - -### Unsupported Property Types * ListProperty * MapProperty * ObjectProperty * SetProperty + + +### Supported Read-only Property Types +* ReadOnlyStringProperty +* ReadOnlyBooleanProperty +* ReadOnlyDoubleProperty +* ReadOnlyFloatProperty +* ReadOnlyIntegerProperty +* ReadOnlyLongProperty +* ReadOnlyListProperty +* ReadOnlyMapProperty +* ReadOnlyObjectProperty +* ReadOnlySetProperty + + + +### Supported Read-only Wrapper Types +* ReadOnlyStringWrapper +* ReadOnlyBooleanWrapper +* ReadOnlyDoubleWrapper +* ReadOnlyFloatWrapper +* ReadOnlyIntegerWrapper +* ReadOnlyLongWrapper +* ReadOnlyListWrapper +* ReadOnlyMapWrapper +* ReadOnlyObjectWrapper +* ReadOnlySetWrapper