javafx: Add properties defined with @NamedArg to the resources for inspection of...
authorPavel Dolgov <pavel.dolgov@jetbrains.com>
Fri, 18 Mar 2016 16:05:15 +0000 (19:05 +0300)
committerPavel Dolgov <pavel.dolgov@jetbrains.com>
Fri, 18 Mar 2016 16:05:59 +0000 (19:05 +0300)
plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxGenerateDefaultPropertyValuesScript.java
plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxRedundantPropertyValueInspection8.txt

index 6ad78d30c6eff376ca14849de237e746061687ef..2458c08de5e8e836621bdd5c486a4f40340d3599 100644 (file)
@@ -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<String, Object> 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<String, String> shareableProperties =
-                  declaredProperties.computeIfAbsent(declaringClass.getName(), unused -> new TreeMap<>());
-                final String sharedValue = shareableProperties.get(propName);
+              final Map<String, String> 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<String> 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<String> 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<String> {
+    final Set<String> names = new TreeSet<>();
+    final Map<String, Set<Type>> types = new TreeMap<>();
+    final Map<String, Set<Object>> values = new TreeMap<>();
+
+    void add(String name, Class<?> type, Object value) {
+      names.add(name);
+      types.computeIfAbsent(name, n -> new HashSet<Type>()).add(type);
+      values.computeIfAbsent(name, n -> new HashSet<Object>()).add(value);
+    }
+
+    boolean isEmpty() {
+      return names.isEmpty();
+    }
+
+    @Override
+    public Iterator<String> iterator() {
+      return names.iterator();
+    }
+
+    public Type getType(String name) {
+      final Set<Type> typeSet = types.get(name);
+      if (typeSet != null && typeSet.size() == 1) {
+        return typeSet.iterator().next();
+      }
+      return null;
+    }
+
+    public Object getValue(String name) {
+      final Set<Object> valueSet = values.get(name);
+      if (valueSet != null && valueSet.size() == 1) {
+        return valueSet.iterator().next();
+      }
+      return null;
+    }
+  }
+
+  @NotNull
+  private static Map<String, Object> 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<String, Object> 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());
   }
index 62dc185e1988606ce236ef9bd2a694a70f657ff3..01f3493859875e9e38e30916d94428effbca8ad0 100644 (file)
@@ -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