• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 26101908636

19 May 2026 01:55PM UTC coverage: 70.982% (+0.003%) from 70.979%
26101908636

Pull #1859

github

web-flow
Merge cf4a7f717 into b4eeee25f
Pull Request #1859: #1392: Smart completions

4472 of 6964 branches covered (64.22%)

Branch coverage included in aggregate %.

11521 of 15567 relevant lines covered (74.01%)

3.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

11.27
cli/src/main/java/com/devonfw/tools/ide/property/PathProperty.java
1
package com.devonfw.tools.ide.property;
2

3
import java.io.IOException;
4
import java.nio.file.Files;
5
import java.nio.file.Path;
6
import java.util.stream.Stream;
7

8
import com.devonfw.tools.ide.commandlet.Commandlet;
9
import com.devonfw.tools.ide.completion.CompletionCandidateCollector;
10
import com.devonfw.tools.ide.context.IdeContext;
11
import com.devonfw.tools.ide.validation.PropertyValidator;
12
import com.devonfw.tools.ide.validation.ValidationResult;
13
import com.devonfw.tools.ide.validation.ValidationState;
14

15
/**
16
 * {@link Property} with {@link Path} as {@link #getValueType() value type}.
17
 */
18
public class PathProperty extends Property<Path> {
19

20
  private final boolean mustExist;
21

22
  /**
23
   * The constructor.
24
   *
25
   * @param name the {@link #getName() property name}.
26
   * @param required the {@link #isRequired() required flag}.
27
   * @param mustExist the {@link #isPathRequiredToExist() required to exist flag}.
28
   * @param alias the {@link #getAlias() property alias}.
29
   */
30
  public PathProperty(String name, boolean required, String alias, boolean mustExist) {
31

32
    this(name, required, alias, mustExist, false, null);
×
33
  }
×
34

35
  /**
36
   * The constructor.
37
   *
38
   * @param name the {@link #getName() property name}.
39
   * @param required the {@link #isRequired() required flag}.
40
   * @param alias the {@link #getAlias() property alias}.
41
   * @param mustExist the {@link #isPathRequiredToExist() required to exist flag}.
42
   * @param placeholder whether this property is substituted by some value or literal
43
   * @param validator the {@link PropertyValidator} used to {@link #validate() validate} the {@link #getValue() value}.
44
   */
45
  public PathProperty(String name, boolean required, String alias, boolean mustExist, boolean placeholder, PropertyValidator<Path> validator) {
46

47
    super(name, required, alias, false, placeholder, validator);
8✔
48
    this.mustExist = mustExist;
3✔
49
  }
1✔
50

51
  @Override
52
  public Class<Path> getValueType() {
53

54
    return Path.class;
×
55
  }
56

57
  @Override
58
  public Path parse(String valueAsString, IdeContext context) {
59

60
    return Path.of(valueAsString);
×
61
  }
62

63
  @Override
64
  public ValidationResult validate() {
65
    ValidationState state = new ValidationState(this.getNameOrAlias());
6✔
66
    for (Path path : this.value) {
7!
67
      if (path != null && Files.exists(path)) {
×
68
        if (isPathRequiredToBeFile() && !Files.isRegularFile(path)) {
×
69
          state.addErrorMessage("Path " + path + " is not a file.");
×
70
        } else if (isPathRequiredToBeFolder() && !Files.isDirectory(path)) {
×
71
          state.addErrorMessage("Path " + path + " is not a folder.");
×
72
        }
73
      } else if (isPathRequiredToExist()) {
×
74
        state.addErrorMessage("Path " + path + " does not exist.");
×
75
      }
76
    }
×
77
    state.add(super.validate());
4✔
78
    return state;
2✔
79
  }
80

81
  /**
82
   * @return {@code true} if the {@link Path} {@link #getValue() value} must {@link Files#exists(Path, java.nio.file.LinkOption...) exist} if set, {@code false}
83
   *     otherwise.
84
   */
85
  protected boolean isPathRequiredToExist() {
86

87
    return this.mustExist;
×
88
  }
89

90
  /**
91
   * @return {@code true} if the {@link Path} {@link #getValue() value} must be a {@link Files#isDirectory(Path, java.nio.file.LinkOption...) folder} if it
92
   *     exists, {@code false} otherwise.
93
   */
94
  protected boolean isPathRequiredToBeFolder() {
95

96
    return false;
×
97
  }
98

99
  /**
100
   * @return {@code true} if the {@link Path} {@link #getValue() value} must be a {@link Files#isRegularFile(Path, java.nio.file.LinkOption...) file} if it
101
   *     exists, {@code false} otherwise.
102
   */
103
  protected boolean isPathRequiredToBeFile() {
104

105
    return false;
×
106
  }
107

108
  @Override
109
  protected void completeValue(String arg, IdeContext context, Commandlet commandlet, CompletionCandidateCollector collector) {
110

111
    Path path = Path.of(arg);
×
112
    Path parent = path.getParent();
×
113
    //set a default parent directory when unable to obtain the parent directory
114
    if (parent == null) {
×
115
      parent = Path.of(".");
×
116
    }
117
    String filename = path.getFileName().toString();
×
118
    completeValuesFromFolder(parent, filename, context, commandlet, collector);
×
119
  }
×
120

121
  /**
122
   * @param folder the {@link Path} to the directory where to search for the file.
123
   * @param filename the filename (prefix) to complete.
124
   * @param context the {@link IdeContext}.
125
   * @param commandlet the owning {@link Commandlet}.
126
   * @param collector the {@link CompletionCandidateCollector}.
127
   */
128
  protected void completeValuesFromFolder(Path folder, String filename, IdeContext context, Commandlet commandlet, CompletionCandidateCollector collector) {
129

130
    if (Files.isDirectory(folder)) {
×
131
      try (Stream<Path> children = Files.list(folder)) {
×
132
        children.filter(child -> isValidPath(child, filename))
×
133
            .forEach(child -> collector.add(getPathForCompletion(child, context, commandlet), null));
×
134
      } catch (IOException e) {
×
135
        throw new IllegalStateException(e);
×
136
      }
×
137
    }
138
  }
×
139

140
  /**
141
   * @param path the {@link Path} that has been found via completion.
142
   * @param context the {@link IdeContext}.
143
   * @param commandlet the owning {@link Commandlet}.
144
   * @return the {@link String} to {@link CompletionCandidateCollector#add(String, String, Property, Commandlet) add} as completion candidate.
145
   */
146
  protected String getPathForCompletion(Path path, IdeContext context, Commandlet commandlet) {
147

148
    return path.toString();
×
149
  }
150

151
  private boolean isValidPath(Path path, String filename) {
152

153
    if (isPathRequiredToBeFile() && !Files.isRegularFile(path)) {
×
154
      return false; // isnt this wrong? How can I use completion to complete a file in a sub-folder?
×
155
    } else if (isPathRequiredToBeFolder() && !Files.isDirectory(path)) {
×
156
      return false;
×
157
    }
158
    return path.getFileName().toString().startsWith(filename);
×
159
  }
160

161
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc