diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxGenerateDefaultPropertyValuesScript.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxGenerateDefaultPropertyValuesScript.java index 6ad78d30c6ef..2458c08de5e8 100644 --- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxGenerateDefaultPropertyValuesScript.java +++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxGenerateDefaultPropertyValuesScript.java @@ -2,6 +2,9 @@ package org.jetbrains.plugins.javaFX.fxml; import javafx.application.Application; import javafx.application.Platform; +import javafx.beans.NamedArg; +import javafx.beans.value.WritableValue; +import javafx.event.Event; import javafx.geometry.NodeOrientation; import javafx.geometry.Pos; import javafx.scene.AccessibleRole; @@ -154,6 +157,7 @@ public class JavaFxGenerateDefaultPropertyValuesScript extends Application { bindings.add(methodDesc.getName()); } } + Map constructorNamedArgValues = constructorNamedArgValues(currentClass); Object instance = null; for (PropertyDescriptor desc : info.getPropertyDescriptors()) { @@ -162,15 +166,18 @@ public class JavaFxGenerateDefaultPropertyValuesScript extends Application { if (ourSkippedProperties.contains(propQualifiedName)) continue; final Method setter = desc.getWriteMethod(); final boolean hasBinding = bindings.contains(propName + "Property"); - if (setter == null || !hasBinding) continue; - final Type type = setter.getGenericParameterTypes()[0]; - if (type instanceof Class && isSupportedPropertyType((Class)type)) { + final Object value; + final Class declaringClass; + final Type type; + if (setter != null && + hasBinding && + (type = setter.getGenericParameterTypes()[0]) instanceof Class && + isSupportedPropertyType((Class)type)) { if (instance == null) { instance = instantiate(currentClass); if (instance == null) break; } - final Object value; final Method getter = desc.getReadMethod(); try { value = getter.invoke(instance); @@ -178,29 +185,34 @@ public class JavaFxGenerateDefaultPropertyValuesScript extends Application { catch (IllegalAccessException | InvocationTargetException e) { throw new RuntimeException("Can't invoke " + getter + " on " + currentClass, e); } - if (value != null) { - final Class declaringClass = getter.getDeclaringClass(); - final DefaultValue newValue = new DefaultValue(value, declaringClass.getName()); - if (declaringClass.getName().startsWith("javafx")) { - defaultPropertyValues - .computeIfAbsent(currentClass.getName(), unused -> new TreeMap<>()) - .put(propName, newValue); - } + declaringClass = getter.getDeclaringClass(); + } + else { + value = constructorNamedArgValues.get(propName); + if (value == null) continue; + declaringClass = currentClass; + } + if (value != null) { + final DefaultValue newValue = new DefaultValue(value, declaringClass.getName()); + if (declaringClass.getName().startsWith("javafx")) { + defaultPropertyValues + .computeIfAbsent(currentClass.getName(), unused -> new TreeMap<>()) + .put(propName, newValue); + } - final Map shareableProperties = - declaredProperties.computeIfAbsent(declaringClass.getName(), unused -> new TreeMap<>()); - final String sharedValue = shareableProperties.get(propName); + final Map shareableProperties = + declaredProperties.computeIfAbsent(declaringClass.getName(), unused -> new TreeMap<>()); + final String sharedValue = shareableProperties.get(propName); - if (sharedValue == null) { - shareableProperties.put(propName, newValue.getValueText()); - } - else if (!sharedValue.equals(newValue.getValueText())) { - final Set multipleValues = overriddenProperties - .computeIfAbsent(declaringClass.getName(), unused -> new TreeMap<>()) - .computeIfAbsent(propName, unused -> new TreeSet<>()); - multipleValues.add(sharedValue); - multipleValues.add(newValue.getValueText()); - } + if (sharedValue == null) { + shareableProperties.put(propName, newValue.getValueText()); + } + else if (!sharedValue.equals(newValue.getValueText())) { + final Set multipleValues = overriddenProperties + .computeIfAbsent(declaringClass.getName(), unused -> new TreeMap<>()) + .computeIfAbsent(propName, unused -> new TreeSet<>()); + multipleValues.add(sharedValue); + multipleValues.add(newValue.getValueText()); } } } @@ -269,6 +281,124 @@ public class JavaFxGenerateDefaultPropertyValuesScript extends Application { ourSkippedProperties.forEach(propName -> System.out.println("-- " + propName)); } + private static class Args implements Iterable { + final Set names = new TreeSet<>(); + final Map> types = new TreeMap<>(); + final Map> values = new TreeMap<>(); + + void add(String name, Class type, Object value) { + names.add(name); + types.computeIfAbsent(name, n -> new HashSet()).add(type); + values.computeIfAbsent(name, n -> new HashSet()).add(value); + } + + boolean isEmpty() { + return names.isEmpty(); + } + + @Override + public Iterator iterator() { + return names.iterator(); + } + + public Type getType(String name) { + final Set typeSet = types.get(name); + if (typeSet != null && typeSet.size() == 1) { + return typeSet.iterator().next(); + } + return null; + } + + public Object getValue(String name) { + final Set valueSet = values.get(name); + if (valueSet != null && valueSet.size() == 1) { + return valueSet.iterator().next(); + } + return null; + } + } + + @NotNull + private static Map constructorNamedArgValues(Class aClass) { + if (aClass.isInterface() || + aClass.isAnnotation() || + WritableValue.class.isAssignableFrom(aClass) || + Event.class.isAssignableFrom(aClass)) { + return Collections.emptyMap(); + } + final Constructor[] constructors = aClass.getConstructors(); + final Args args = new Args(); + for (Constructor constructor : constructors) { + final Parameter[] parameters = constructor.getParameters(); + for (Parameter parameter : parameters) { + final Class type = parameter.getType(); + if (type.isPrimitive() || type.isEnum() || type == String.class) { + final NamedArg namedArg = parameter.getAnnotation(NamedArg.class); + if (namedArg == null) continue; + final String name = namedArg.value(); + if (!name.isEmpty()) { + final String defaultValue = namedArg.defaultValue(); + if ((type == String.class || type.isEnum()) && !defaultValue.isEmpty() && !"\"\"".equals(defaultValue)) { + args.add(name, type, defaultValue); + } + else if (type == boolean.class) { + args.add(name, type, Boolean.valueOf(defaultValue)); + } + else if (type == int.class) { + try { + args.add(name, type, Integer.valueOf(defaultValue)); + } + catch (NumberFormatException e) { + args.add(name, type, Integer.valueOf(0)); + } + } + else if (type == long.class) { + try { + args.add(name, type, Long.valueOf(defaultValue)); + } + catch (NumberFormatException e) { + args.add(name, type, Long.valueOf(0)); + } + } + else if (type == double.class) { + try { + args.add(name, type, Double.valueOf(defaultValue)); + } + catch (NumberFormatException e) { + args.add(name, type, Double.valueOf(0)); + } + } + else if (type == float.class) { + try { + args.add(name, type, Float.valueOf(defaultValue)); + } + catch (NumberFormatException e) { + args.add(name, type, Float.valueOf(0)); + } + } + else if (!type.isEnum() && type != String.class) { + System.err.println("pri " + type); + } + } + } + } + } + if (args.isEmpty()) return Collections.emptyMap(); + + Map result = new TreeMap<>(); + for (String name : args) { + final Type type = args.getType(name); + if (type != null) { + final Object value = args.getValue(name); + if (value != null) { + result.put(name, value); + } + } + } + return result; + } + + private static boolean areValuesEqual(DefaultValue first, DefaultValue second) { return second.getValueText().equals(first.getValueText()); } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxRedundantPropertyValueInspection8.txt b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxRedundantPropertyValueInspection8.txt index 62dc185e1988..01f349385987 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxRedundantPropertyValueInspection8.txt +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxRedundantPropertyValueInspection8.txt @@ -77,9 +77,34 @@ javafx.animation.TranslateTransition#fromZ=NaN javafx.animation.TranslateTransition#toX=NaN javafx.animation.TranslateTransition#toY=NaN javafx.animation.TranslateTransition#toZ=NaN +javafx.geometry.BoundingBox#depth=0.0 +javafx.geometry.BoundingBox#height=0.0 +javafx.geometry.BoundingBox#minX=0.0 +javafx.geometry.BoundingBox#minY=0.0 +javafx.geometry.BoundingBox#minZ=0.0 +javafx.geometry.BoundingBox#width=0.0 +javafx.geometry.Dimension2D#height=0.0 +javafx.geometry.Dimension2D#width=0.0 +javafx.geometry.Insets#bottom=0.0 +javafx.geometry.Insets#left=0.0 +javafx.geometry.Insets#right=0.0 +javafx.geometry.Insets#top=0.0 +javafx.geometry.Point2D#x=0.0 +javafx.geometry.Point2D#y=0.0 +javafx.geometry.Point3D#x=0.0 +javafx.geometry.Point3D#y=0.0 +javafx.geometry.Point3D#z=0.0 +javafx.geometry.Rectangle2D#height=0.0 +javafx.geometry.Rectangle2D#minX=0.0 +javafx.geometry.Rectangle2D#minY=0.0 +javafx.geometry.Rectangle2D#width=0.0 +javafx.print.PageRange#endPage=0 +javafx.print.PageRange#startPage=0 javafx.scene.Camera#farClip=100.0 javafx.scene.Camera#nearClip=0.1 javafx.scene.Group#autoSizeChildren=true +javafx.scene.ImageCursor#hotspotX=0.0 +javafx.scene.ImageCursor#hotspotY=0.0 javafx.scene.LightBase#lightOn=true javafx.scene.Node#cache=false javafx.scene.Node#cacheHint=DEFAULT @@ -101,6 +126,7 @@ javafx.scene.Node#translateZ=0.0 javafx.scene.Node#visible=true javafx.scene.PerspectiveCamera#fieldOfView=30.0 javafx.scene.PerspectiveCamera#verticalFieldOfView=true +javafx.scene.Scene#depthBuffer=false javafx.scene.canvas.Canvas#height=0.0 javafx.scene.canvas.Canvas#width=0.0 javafx.scene.chart.Axis#animated=true @@ -149,6 +175,8 @@ javafx.scene.control.Dialog#resizable=false javafx.scene.control.Dialog#title=Confirmation javafx.scene.control.DialogPane#expanded=false javafx.scene.control.Hyperlink#visited=false +javafx.scene.control.IndexRange#end=0 +javafx.scene.control.IndexRange#start=0 javafx.scene.control.Labeled#contentDisplay=LEFT javafx.scene.control.Labeled#ellipsisString=... javafx.scene.control.Labeled#graphicTextGap=4.0 @@ -237,6 +265,7 @@ javafx.scene.control.TableColumnBase#sortable=true javafx.scene.control.TableColumnBase#style= javafx.scene.control.TableColumnBase#text= javafx.scene.control.TableColumnBase#visible=true +javafx.scene.control.TablePosition#row=0 javafx.scene.control.TableView#editable=false javafx.scene.control.TableView#fixedCellSize=-1.0 javafx.scene.control.TableView#tableMenuButtonVisible=false @@ -263,6 +292,7 @@ javafx.scene.control.Tooltip#textOverrun=ELLIPSIS javafx.scene.control.Tooltip#wrapText=false javafx.scene.control.TreeItem#expanded=false javafx.scene.control.TreeTableColumn#sortType=ASCENDING +javafx.scene.control.TreeTablePosition#row=0 javafx.scene.control.TreeTableView#editable=false javafx.scene.control.TreeTableView#fixedCellSize=-1.0 javafx.scene.control.TreeTableView#showRoot=true @@ -346,17 +376,57 @@ javafx.scene.effect.Shadow#blurType=THREE_PASS_BOX javafx.scene.effect.Shadow#height=21.0 javafx.scene.effect.Shadow#radius=10.0 javafx.scene.effect.Shadow#width=21.0 +javafx.scene.image.Image#backgroundLoading=false +javafx.scene.image.Image#preserveRatio=false +javafx.scene.image.Image#requestedHeight=0.0 +javafx.scene.image.Image#requestedWidth=0.0 javafx.scene.image.ImageView#fitHeight=0.0 javafx.scene.image.ImageView#fitWidth=0.0 javafx.scene.image.ImageView#preserveRatio=false javafx.scene.image.ImageView#smooth=true javafx.scene.image.ImageView#x=0.0 javafx.scene.image.ImageView#y=0.0 +javafx.scene.image.WritableImage#height=0 +javafx.scene.image.WritableImage#width=0 +javafx.scene.input.TouchPoint#id=0 +javafx.scene.input.TouchPoint#screenX=0.0 +javafx.scene.input.TouchPoint#screenY=0.0 +javafx.scene.input.TouchPoint#x=0.0 +javafx.scene.input.TouchPoint#y=0.0 +javafx.scene.layout.BackgroundPosition#horizontalAsPercentage=false +javafx.scene.layout.BackgroundPosition#horizontalPosition=0.0 +javafx.scene.layout.BackgroundPosition#verticalAsPercentage=false +javafx.scene.layout.BackgroundPosition#verticalPosition=0.0 +javafx.scene.layout.BackgroundSize#contain=false +javafx.scene.layout.BackgroundSize#cover=false +javafx.scene.layout.BackgroundSize#height=0.0 +javafx.scene.layout.BackgroundSize#heightAsPercentage=false +javafx.scene.layout.BackgroundSize#width=0.0 +javafx.scene.layout.BackgroundSize#widthAsPercentage=false +javafx.scene.layout.BorderImage#filled=false +javafx.scene.layout.BorderStrokeStyle#dashOffset=0.0 +javafx.scene.layout.BorderStrokeStyle#miterLimit=0.0 +javafx.scene.layout.BorderWidths#bottom=0.0 +javafx.scene.layout.BorderWidths#bottomAsPercentage=false +javafx.scene.layout.BorderWidths#left=0.0 +javafx.scene.layout.BorderWidths#leftAsPercentage=false +javafx.scene.layout.BorderWidths#right=0.0 +javafx.scene.layout.BorderWidths#rightAsPercentage=false +javafx.scene.layout.BorderWidths#top=0.0 +javafx.scene.layout.BorderWidths#topAsPercentage=false javafx.scene.layout.ColumnConstraints#fillWidth=true javafx.scene.layout.ColumnConstraints#maxWidth=-1.0 javafx.scene.layout.ColumnConstraints#minWidth=-1.0 javafx.scene.layout.ColumnConstraints#percentWidth=-1.0 javafx.scene.layout.ColumnConstraints#prefWidth=-1.0 +javafx.scene.layout.CornerRadii#bottomLeftHorizontalRadius=0.0 +javafx.scene.layout.CornerRadii#bottomLeftVerticalRadius=0.0 +javafx.scene.layout.CornerRadii#bottomRightHorizontalRadius=0.0 +javafx.scene.layout.CornerRadii#bottomRightVerticalRadius=0.0 +javafx.scene.layout.CornerRadii#topLeftHorizontalRadius=0.0 +javafx.scene.layout.CornerRadii#topLeftVerticalRadius=0.0 +javafx.scene.layout.CornerRadii#topRightHorizontalRadius=0.0 +javafx.scene.layout.CornerRadii#topRightVerticalRadius=0.0 javafx.scene.layout.FlowPane#alignment=TOP_LEFT javafx.scene.layout.FlowPane#columnHalignment=LEFT javafx.scene.layout.FlowPane#hgap=0.0 @@ -408,7 +478,28 @@ javafx.scene.media.MediaView#preserveRatio=true javafx.scene.media.MediaView#smooth=true javafx.scene.media.MediaView#x=0.0 javafx.scene.media.MediaView#y=0.0 +javafx.scene.paint.Color#blue=0.0 +javafx.scene.paint.Color#green=0.0 +javafx.scene.paint.Color#opacity=1.0 +javafx.scene.paint.Color#red=0.0 +javafx.scene.paint.ImagePattern#height=0.0 +javafx.scene.paint.ImagePattern#proportional=false +javafx.scene.paint.ImagePattern#width=0.0 +javafx.scene.paint.ImagePattern#x=0.0 +javafx.scene.paint.ImagePattern#y=0.0 +javafx.scene.paint.LinearGradient#endX=1.0 +javafx.scene.paint.LinearGradient#endY=1.0 +javafx.scene.paint.LinearGradient#proportional=true +javafx.scene.paint.LinearGradient#startX=0.0 +javafx.scene.paint.LinearGradient#startY=0.0 javafx.scene.paint.PhongMaterial#specularPower=32.0 +javafx.scene.paint.RadialGradient#centerX=0.0 +javafx.scene.paint.RadialGradient#centerY=0.0 +javafx.scene.paint.RadialGradient#focusAngle=0.0 +javafx.scene.paint.RadialGradient#focusDistance=0.0 +javafx.scene.paint.RadialGradient#proportional=true +javafx.scene.paint.RadialGradient#radius=1.0 +javafx.scene.paint.Stop#offset=0.0 javafx.scene.shape.Arc#centerX=0.0 javafx.scene.shape.Arc#centerY=0.0 javafx.scene.shape.Arc#length=0.0 @@ -489,6 +580,7 @@ javafx.scene.shape.Shape3D#cullFace=BACK javafx.scene.shape.Shape3D#drawMode=FILL javafx.scene.shape.Sphere#radius=1.0 javafx.scene.shape.VLineTo#y=0.0 +javafx.scene.text.Font#size=0.0 javafx.scene.text.Text#boundsType=LOGICAL javafx.scene.text.Text#fontSmoothingType=GRAY javafx.scene.text.Text#impl_caretBias=true @@ -535,6 +627,7 @@ javafx.scene.transform.Shear#y=0.0 javafx.scene.transform.Translate#x=0.0 javafx.scene.transform.Translate#y=0.0 javafx.scene.transform.Translate#z=0.0 +javafx.scene.web.PopupFeatures#resizable=false javafx.scene.web.WebEngine#javaScriptEnabled=true javafx.scene.web.WebView#contextMenuEnabled=true javafx.scene.web.WebView#fontScale=1.0