Skip to content

Commit 8f52bfa

Browse files
committed
Merge branch 'use-designer-bindings'
2 parents 4ab1795 + 37b6f09 commit 8f52bfa

File tree

17 files changed

+335
-80
lines changed

17 files changed

+335
-80
lines changed

.idea/runConfigurations/Designer__JRE_11_.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/Designer__JRE_8_.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/watcherTasks.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/java/net/sourceforge/pmd/util/fxdesigner/NodeDetailPaneController.java

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,37 @@
55
package net.sourceforge.pmd.util.fxdesigner;
66

77
import java.util.Arrays;
8-
import java.util.Collections;
8+
import java.util.Comparator;
99
import java.util.Iterator;
1010
import java.util.List;
1111

1212
import org.reactfx.EventStreams;
13+
import org.reactfx.collection.LiveList;
1314
import org.reactfx.value.Val;
1415
import org.reactfx.value.Var;
1516

1617
import net.sourceforge.pmd.lang.ast.Node;
1718
import net.sourceforge.pmd.lang.ast.xpath.Attribute;
19+
import net.sourceforge.pmd.util.designerbindings.DesignerBindings;
20+
import net.sourceforge.pmd.util.designerbindings.DesignerBindings.AdditionalInfo;
21+
import net.sourceforge.pmd.util.designerbindings.DesignerBindings.DefaultDesignerBindings;
1822
import net.sourceforge.pmd.util.fxdesigner.app.AbstractController;
1923
import net.sourceforge.pmd.util.fxdesigner.app.DesignerRoot;
2024
import net.sourceforge.pmd.util.fxdesigner.app.NodeSelectionSource;
2125
import net.sourceforge.pmd.util.fxdesigner.util.DataHolder;
2226
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
2327
import net.sourceforge.pmd.util.fxdesigner.util.beans.SettingsPersistenceUtil.PersistentProperty;
28+
import net.sourceforge.pmd.util.fxdesigner.util.controls.AttributeNameTableCell;
2429

2530
import javafx.collections.FXCollections;
2631
import javafx.collections.ObservableList;
2732
import javafx.fxml.FXML;
2833
import javafx.scene.control.Label;
2934
import javafx.scene.control.ListView;
35+
import javafx.scene.control.TableColumn;
36+
import javafx.scene.control.TableView;
3037
import javafx.scene.control.ToggleButton;
38+
import javafx.scene.control.Tooltip;
3139

3240
/**
3341
* The "Attributes" pane.
@@ -36,14 +44,22 @@
3644
*/
3745
public class NodeDetailPaneController extends AbstractController implements NodeSelectionSource {
3846

39-
/** List of attribute names that are ignored if {@link #isHideCommonAttributes()} is true. */
47+
/**
48+
* List of attribute names that are ignored if {@link #isHideCommonAttributes()} is true.
49+
*/
4050
private static final List<String> IGNORABLE_ATTRIBUTES =
4151
Arrays.asList("BeginLine", "EndLine", "BeginColumn", "EndColumn", "FindBoundary", "SingleLine");
4252

53+
@FXML
54+
private TableView<Attribute> xpathAttributesTableView;
55+
@FXML
56+
private TableColumn<Attribute, String> attrValueColumn;
57+
@FXML
58+
private TableColumn<Attribute, String> attrNameColumn;
4359
@FXML
4460
private ToggleButton hideCommonAttributesToggle;
4561
@FXML
46-
private ListView<String> xpathAttributesListView;
62+
private ListView<String> additionalInfoListView;
4763

4864

4965
protected NodeDetailPaneController(DesignerRoot root) {
@@ -52,7 +68,7 @@ protected NodeDetailPaneController(DesignerRoot root) {
5268

5369
@Override
5470
protected void beforeParentInit() {
55-
xpathAttributesListView.setPlaceholder(new Label("No available attributes"));
71+
additionalInfoListView.setPlaceholder(new Label("No additional info"));
5672

5773
Val<Node> currentSelection = initNodeSelectionHandling(getDesignerRoot(), EventStreams.never(), false);
5874

@@ -64,42 +80,56 @@ protected void beforeParentInit() {
6480
.distinct()
6581
.subscribe(show -> setFocusNode(currentSelection.getValue(), new DataHolder()));
6682

83+
84+
attrValueColumn.setCellValueFactory(param -> Val.constant(DesignerUtil.attrToXpathString(param.getValue())));
85+
attrNameColumn.setCellValueFactory(param -> Val.constant("@" + param.getValue().getName()));
86+
attrNameColumn.setCellFactory(col -> new AttributeNameTableCell());
87+
88+
Label valueColGraphic = new Label("Value");
89+
valueColGraphic.setTooltip(new Tooltip("This is the XPath 2.0 representation"));
90+
attrValueColumn.setGraphic(valueColGraphic);
6791
}
6892

6993
@Override
7094
public void setFocusNode(final Node node, DataHolder options) {
71-
xpathAttributesListView.setItems(getAttributes(node));
95+
xpathAttributesTableView.setItems(getAttributes(node));
96+
if (node == null) {
97+
additionalInfoListView.setItems(FXCollections.emptyObservableList());
98+
return;
99+
}
100+
DesignerBindings bindings = languageBindingsProperty().getOrElse(DefaultDesignerBindings.getInstance());
101+
ObservableList<AdditionalInfo> additionalInfo = FXCollections.observableArrayList(bindings.getAdditionalInfo(node));
102+
additionalInfo.sort(Comparator.comparing(AdditionalInfo::getSortKey));
103+
additionalInfoListView.setItems(LiveList.map(additionalInfo, AdditionalInfo::getDisplayString));
72104
}
73105

74106
/**
75107
* Gets the XPath attributes of the node for display within a listview.
76108
*/
77-
private ObservableList<String> getAttributes(Node node) {
109+
private ObservableList<Attribute> getAttributes(Node node) {
78110
if (node == null) {
111+
xpathAttributesTableView.setPlaceholder(new Label("Select a node to show its attributes"));
79112
return FXCollections.emptyObservableList();
80113
}
81114

82-
ObservableList<String> result = FXCollections.observableArrayList();
115+
ObservableList<Attribute> result = FXCollections.observableArrayList();
83116
Iterator<Attribute> attributeAxisIterator = node.getXPathAttributesIterator();
84117
while (attributeAxisIterator.hasNext()) {
85118
Attribute attribute = attributeAxisIterator.next();
86119

87120
if (!(isHideCommonAttributes() && IGNORABLE_ATTRIBUTES.contains(attribute.getName()))) {
88121

89122
try {
90-
// TODO the display should be handled in a ListCell
91-
result.add(attribute.getName() + " = "
92-
+ ((attribute.getValue() != null) ? attribute.getStringValue() : "null"));
123+
result.add(attribute);
93124
} catch (Exception ignored) {
94125
// some attributes throw eg numberformat exceptions
95126
}
96127

97128
}
98129
}
99130

100-
DesignerUtil.getResolvedType(node).map(t -> "typeIs() = " + t).ifPresent(result::add);
101-
102-
Collections.sort(result);
131+
result.sort(Comparator.comparing(Attribute::getName));
132+
xpathAttributesTableView.setPlaceholder(new Label("No available attributes"));
103133
return result;
104134
}
105135

src/main/java/net/sourceforge/pmd/util/fxdesigner/app/ApplicationComponent.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import net.sourceforge.pmd.lang.Language;
1313
import net.sourceforge.pmd.lang.LanguageVersion;
14+
import net.sourceforge.pmd.lang.LanguageVersionHandler;
15+
import net.sourceforge.pmd.util.designerbindings.DesignerBindings;
1416
import net.sourceforge.pmd.util.fxdesigner.SourceEditorController;
1517
import net.sourceforge.pmd.util.fxdesigner.app.services.AppServiceDescriptor;
1618
import net.sourceforge.pmd.util.fxdesigner.app.services.EventLogger;
@@ -61,6 +63,14 @@ default LanguageVersion getGlobalLanguageVersion() {
6163
}
6264

6365

66+
default Val<DesignerBindings> languageBindingsProperty() {
67+
return getService(DesignerRoot.AST_MANAGER)
68+
.languageVersionProperty()
69+
.map(LanguageVersion::getLanguageVersionHandler)
70+
.map(LanguageVersionHandler::getDesignerBindings);
71+
}
72+
73+
6474
/**
6575
* Gets the logger of the application. Events pushed to the logger
6676
* are filtered then forwarded to the Event Log control.

src/main/java/net/sourceforge/pmd/util/fxdesigner/app/DesignerRoot.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public interface DesignerRoot {
7676
AppServiceDescriptor<TreeRendererRegistry> TREE_RENDERER_REGISTRY = new AppServiceDescriptor<>(TreeRendererRegistry.class);
7777

7878

79+
7980
/**
8081
* Gets the instance of a service shared by the app.
8182
*

src/main/java/net/sourceforge/pmd/util/fxdesigner/util/DesignerUtil.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package net.sourceforge.pmd.util.fxdesigner.util;
66

77
import java.io.PrintStream;
8-
import java.lang.reflect.InvocationTargetException;
98
import java.net.URL;
109
import java.util.ArrayList;
1110
import java.util.Arrays;
@@ -27,12 +26,14 @@
2726
import java.util.stream.Collectors;
2827

2928
import org.apache.commons.lang3.ArrayUtils;
29+
import org.apache.commons.lang3.StringEscapeUtils;
3030
import org.apache.commons.lang3.exception.ExceptionUtils;
3131
import org.checkerframework.checker.nullness.qual.NonNull;
3232
import org.reactfx.Subscription;
3333
import org.reactfx.value.Var;
3434

3535
import net.sourceforge.pmd.lang.ast.Node;
36+
import net.sourceforge.pmd.lang.ast.xpath.Attribute;
3637
import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery;
3738
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
3839
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
@@ -50,6 +51,7 @@
5051
import javafx.scene.control.Toggle;
5152
import javafx.scene.control.ToggleGroup;
5253
import javafx.scene.control.Tooltip;
54+
import javafx.scene.text.Text;
5355
import javafx.util.BuilderFactory;
5456
import javafx.util.Callback;
5557
import javafx.util.StringConverter;
@@ -396,26 +398,6 @@ private static void updateProgress(double progress) {
396398
System.out.print(builder);
397399
}
398400

399-
/**
400-
* Attempts to retrieve the type of a java TypeNode reflectively.
401-
*/
402-
public static Optional<Class<?>> getResolvedType(Node node) {
403-
// TODO maybe put some equivalent to TypeNode inside pmd-core
404-
405-
try {
406-
return Optional.of(node.getClass().getMethod("getType"))
407-
.filter(m -> m.getReturnType() == Class.class)
408-
.map(m -> {
409-
try {
410-
return m.invoke(node);
411-
} catch (IllegalAccessException | InvocationTargetException e) {
412-
return null;
413-
}
414-
}).map(type -> (Class<?>) type);
415-
} catch (NoSuchMethodException e) {
416-
return Optional.empty();
417-
}
418-
}
419401

420402
public static BuilderFactory customBuilderFactory(@NonNull DesignerRoot owner) {
421403
return type -> {
@@ -434,4 +416,23 @@ public static BuilderFactory customBuilderFactory(@NonNull DesignerRoot owner) {
434416
}
435417
};
436418
}
419+
420+
421+
public static String attrToXpathString(Attribute attr) {
422+
String stringValue = attr.getStringValue();
423+
Object v = attr.getValue();
424+
if (v instanceof String || v instanceof Enum) {
425+
stringValue = "\"" + StringEscapeUtils.escapeJava(stringValue) + "\"";
426+
} else if (v instanceof Boolean) {
427+
stringValue = v + "()";
428+
}
429+
return String.valueOf(stringValue);
430+
}
431+
432+
433+
public static Text makeStyledText(String text, String cssClass) {
434+
Text matchLabel = new Text(text);
435+
matchLabel.getStyleClass().add(cssClass);
436+
return matchLabel;
437+
}
437438
}

src/main/java/net/sourceforge/pmd/util/fxdesigner/util/autocomplete/matchers/StringMatchUtil.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.util.function.Function;
99
import java.util.stream.Stream;
1010

11+
import net.sourceforge.pmd.util.fxdesigner.util.DesignerUtil;
12+
1113
import javafx.scene.text.Text;
1214
import javafx.scene.text.TextFlow;
1315

@@ -28,10 +30,18 @@ private StringMatchUtil() {
2830
/**
2931
* Selects the best {@link MatchResult} given a list of candidates and a query.
3032
*
31-
* The results are useless unless you provide the {@link MatchSelector} that
32-
* suits your use case.
33+
* <p>The results are useless unless you provide the {@link MatchSelector} that
34+
* suits your use case (limiter).
35+
*
36+
* @param candidates List of stuff to sort
37+
* @param matchExtractor Extracts the searchable text from an item
38+
* @param limiter Selects the best candidates, may process them further to break ties
39+
* @param query Text to search for
3340
*/
34-
public static <T> Stream<MatchResult<T>> filterResults(List<T> candidates, Function<T, String> matchExtractor, String query, MatchSelector<T> limiter) {
41+
public static <T> Stream<MatchResult<T>> filterResults(List<? extends T> candidates,
42+
Function<? super T, String> matchExtractor,
43+
String query,
44+
MatchSelector<T> limiter) {
3545
if (query.length() < MIN_QUERY_LENGTH) {
3646
return Stream.empty();
3747
}
@@ -53,9 +63,7 @@ static Text makeHighlightedText(String match) {
5363

5464

5565
static Text makeNormalText(String text) {
56-
Text matchLabel = new Text(text);
57-
matchLabel.getStyleClass().add("text");
58-
return matchLabel;
66+
return DesignerUtil.makeStyledText(text, "text");
5967
}
6068

6169
}

src/main/java/net/sourceforge/pmd/util/fxdesigner/util/controls/ASTTreeCell.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import net.sourceforge.pmd.util.fxdesigner.app.ApplicationComponent;
1313
import net.sourceforge.pmd.util.fxdesigner.app.DesignerRoot;
1414
import net.sourceforge.pmd.util.fxdesigner.util.controls.SearchableTreeView.SearchableTreeCell;
15+
import net.sourceforge.pmd.util.fxdesigner.util.controls.SearchableTreeView.SearchableTreeItem;
1516

1617
import javafx.scene.control.ContextMenu;
1718
import javafx.scene.control.CustomMenuItem;
@@ -62,6 +63,16 @@ private ContextMenu buildContextMenu(Node item) {
6263
}
6364

6465

66+
@Override
67+
protected void setNonSearchState(SearchableTreeItem<Node> realItem) {
68+
ASTTreeItem astItem = (ASTTreeItem) realItem;
69+
70+
Node node = realItem.getValue();
71+
setText(null);
72+
setGraphic(node == null ? null : astItem.styledPresentableText(node));
73+
}
74+
75+
6576
@Override
6677
public void commonUpdate(Node item) {
6778
setContextMenu(buildContextMenu(item));

0 commit comments

Comments
 (0)