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

moosetechnology / VerveineJ / 23903759964

02 Apr 2026 01:50PM UTC coverage: 52.037% (-0.02%) from 52.057%
23903759964

Pull #211

github

web-flow
Merge 472c33e4a into d731f778d
Pull Request #211: Add an option to choose the runtime library used for bindings by JDT

1977 of 3976 branches covered (49.72%)

Branch coverage included in aggregate %.

8 of 16 new or added lines in 1 file covered. (50.0%)

4371 of 8223 relevant lines covered (53.16%)

2.15 hits per line

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

66.05
/app/src/main/java/fr/inria/verveine/extractor/java/VerveineJOptions.java
1
package fr.inria.verveine.extractor.java;
2

3
import org.eclipse.jdt.core.JavaCore;
4
import org.eclipse.jdt.core.dom.ASTParser;
5

6
import java.io.*;
7
import java.nio.charset.Charset;
8
import java.util.*;
9
import java.util.regex.Pattern;
10

11
public class VerveineJOptions {
12

13
        /**
14
         * Possible options for SourceAnchors: no source anchor, only entities [default], entities and associations
15
         */
16
        public enum AnchorOptions {
3✔
17
                none, entity, assoc;
18✔
18

19
                public static AnchorOptions getValue(String option) {
20
                        switch (option) {
8!
21
                                case "default":
22
                                case "entity":
23
                                        return entity;
2✔
24
                                case "assoc":
25
                                        return assoc;
2✔
26
                                case "none":
27
                                        return none;
×
28
                                default:
29
                                        return null;
×
30
                        }
31
                }
32
        }
33

34

35
        /**
36
         * Name (without extension) of the default file where to put the MSE model
37
         * <p>
38
         * By default, the extension is provided by the output format
39
         */
40
        public final static String OUTPUT_FILE = "output";
41

42
        /**
43
         * Default encodings of the java files to read
44
         */
45
        private static final String DEFAULT_FILE_ENCODING = "UTF-8";
46

47
        /**
48
         * Option for MSE output format
49
         */
50
        public final static String MSE_OUTPUT_FORMAT = "MSE";
51

52
        /**
53
         * Option for JSON output format
54
         */
55
        public final static String JSON_OUTPUT_FORMAT = "JSON";
56

57
        public static final String DEFAULT_CODE_VERSION = JavaCore.VERSION_9;
58

59
        /**
60
         * List of java version option from java 1.1 to java 23 argument
61
         */
62
        private static final Map<String, String> VERSION_MAP = new HashMap<>();
4✔
63

64
        /**
65
         * Init list of java version option
66
         */
67
        static {
68
                // Olds versions of Java can be written 1.x or x
69
                // While newer version can only be written x
70
                for (String version : JavaCore.getAllVersions()) {
10✔
71
                        if (version.contains(".")) {
4✔
72
                                String shortV = version.substring(2);
4✔
73

74
                                VERSION_MAP.put("-" + version, version);
6✔
75
                                VERSION_MAP.put("-" + shortV, version);
6✔
76
                        } else {
1✔
77
                                VERSION_MAP.put("-" + version, version);
6✔
78
                        }
79
                }
1✔
80
        }
1✔
81

82
        /**
83
         * Whether to output all local variables (even those with primitive type) or not (default is not).<br>
84
         * Note: allLocals => not classSummary
85
         */
86
        protected boolean allLocals;
87

88
        /**
89
         * Option: The version of Java expected by the parser
90
         */
91
        protected String codeVers;
92

93
        /**
94
         * Option: Whether to put SourceAnchors in the entities and/or associations
95
         */
96
        protected AnchorOptions anchors;
97

98
        /**
99
         * The arguments that were passed to the parser
100
         * Needed to relativize the source file names
101
         */
102
        protected Collection<String> argPath;
103
        protected Collection<String> argFiles;
104
        protected String[] classPathOptions;
105

106
        /**
107
         * pathnames to exclude from parsing.<br>
108
         * Accepts globbing expressions
109
         */
110
        protected Collection<String> excludePaths;
111

112
        /**
113
         * collection of matchers of file name to process excluding expr (see
114
         */
115
        protected Collection<Pattern> excludeMatchers;
116

117
        /**
118
         * File encoding to use to read java files
119
         */
120
        protected String fileEncoding = DEFAULT_FILE_ENCODING;
3✔
121

122
        /**
123
         * Name of the file where to put the MSE model.
124
         * Defaults to {@link #OUTPUT_FILE}
125
         */
126
        protected String outputFileName;
127

128
        /**
129
         * Format for saving the model in file: MSE or JSON
130
         */
131
        public String outputFormat;
132

133
        /**
134
         * Whether parsing is incremental
135
         * <p>
136
         * Incremental means an entire project is parsed by parts, verveineJ saving and reloading the model
137
         * respectively at the end of an execution and at the satrt of the next one
138
         */
139
        protected boolean incrementalParsing;
140

141
        /**
142
         * If possible, should I use a prettyPrinter
143
         */
144
        protected boolean prettyPrint = false;
3✔
145

146
        /**
147
         * with additional tracing for debugging
148
         */
149
        protected boolean debugging;
150

151
        /**
152
         * Text of comments exported in the model instead of using source anchor
153
         */
154
        protected boolean commentText;
155

156
        /**
157
         * Am I parsing a JDK?
158
         */
159
        protected boolean parsingJdk = false;
3✔
160
        
161
        /**
162
         * Path to system library for JDT to use 
163
         * (for Java version <= 8 <=> path to rt.jar)
164
         * (for Java version > 8 <=> path to jrt-fs.jar? have not try so to verify in practice)
165
         */
166
        protected String pathToSystemLibrary;
167
        
168

169
        public VerveineJOptions() {
2✔
170
                this.allLocals = false;
3✔
171
                this.codeVers = null;
3✔
172
                this.commentText = false;
3✔
173
                this.incrementalParsing = false;
3✔
174
                this.outputFileName = null;
3✔
175
                this.outputFormat = null; //We need to know if the user sets this option manually. After parsing options, this will be set to the default format if it is still null.
3✔
176
                this.debugging = false;
3✔
177
        }
1✔
178

179
        public void setOptions( String[] args) {
180
                classPathOptions = new String[] {};
4✔
181
                argPath = new ArrayList<String>();
5✔
182
                argFiles = new ArrayList<String>();
5✔
183
                excludePaths = new ArrayList<String>();
5✔
184

185
                int i = 0;
2✔
186
                while (i < args.length && args[i].trim().startsWith("-")) {
11!
187
                        try {
188
                                i += setOption(args, i);
7✔
189
                        } catch (IllegalArgumentException e) {
1✔
190
                                System.err.println(e.getMessage());
4✔
191
                                usage();
2✔
192
                                throw e;
2✔
193
                        }
1✔
194
                }
195

196
                if (JSON_OUTPUT_FORMAT.equalsIgnoreCase(outputFormat) && (incrementalParsing) ) {
8!
197
                        IllegalArgumentException illegalArgumentException = new IllegalArgumentException("-i option requires mse format.");
5✔
198
                        System.err.println(illegalArgumentException.getMessage());
4✔
199
                        usage();
2✔
200
                        throw illegalArgumentException;
2✔
201
                }
202

203
                if (outputFormat == null) {
3✔
204
                        if (incrementalParsing) {
3✔
205
                                outputFormat = MSE_OUTPUT_FORMAT;
4✔
206
                        } else {
207
                                outputFormat= JSON_OUTPUT_FORMAT;
3✔
208
                        }
209
                }
210

211
                if (outputFileName == null) {
3✔
212
                        outputFileName = VerveineJOptions.OUTPUT_FILE + "." + outputFormat.toLowerCase();
6✔
213
                }
214
                if (codeVers == null) {
3✔
215
                        codeVers = DEFAULT_CODE_VERSION;
3✔
216
                }
217
                if (anchors == null) {
3✔
218
                        anchors = VerveineJOptions.AnchorOptions.getValue("default");
4✔
219
                }
220

221
                while (i < args.length) {
4✔
222
                        String arg = args[i++].trim();
6✔
223
                        if (arg.endsWith(".java") && new File(arg).isFile()) {
10!
224
                                argFiles.add(arg);
6✔
225
                        } else {
226
                                argPath.add(arg);
5✔
227
                        }
228
                }
1✔
229
        }
1✔
230

231
        /**
232
         * treats 1 argument or more starting at position <code>i</code> in the array of arguments <code>args</code>
233
         * @param args TODO
234
         * @param i TODO
235
         * @return The number of argument(s) treated
236
         */
237
        protected int setOption( String[] args, int i) throws IllegalArgumentException {
238
                String arg = args[i].trim();
5✔
239
                int argumentsTreated = 1;
2✔
240

241
                if (arg.equals("-h")) {
4!
242
                        usage();
×
243
                        System.exit(0);
×
244
                }
245
                else if (VERSION_MAP.containsKey(arg)) {
4✔
246
                        setCodeVersion(arg);
4✔
247
                } else if (arg.equals("-alllocals")) {
4✔
248
                        allLocals = true;
4✔
249
                } else if (arg.equals("-prettyPrint")) {
4!
250
                        prettyPrint = true;
×
251
                } else if ((arg.charAt(0) == '-') && (arg.endsWith("cp"))) {
9!
252
                        classPathOptions = setOptionClassPath(classPathOptions, args, i);
8✔
253
                        argumentsTreated++;
2✔
254
                } else if (arg.equals("-encoding")) {
4✔
255
                        setOptionEncoding(args, i);
4✔
256
                        argumentsTreated++;
2✔
257
                } else if (arg.equals("-anchor")) {
4✔
258
                        setOptionAnchor(args, i);
4✔
259
                        argumentsTreated++;
2✔
260
                } else if (arg.equals("-commenttext")) {
4✔
261
                        commentText = true;//
4✔
262
                } else if (arg.equals("-format")) {
4✔
263
                        setOptionFormat(args, i);
4✔
264
                        argumentsTreated++;
2✔
265
                } else if (arg.equals("-excludepath")) {
4✔
266
                        if (i < args.length) {
4!
267
                                excludePaths.add(args[i + 1]);
9✔
268
                                argumentsTreated++;
2✔
269
                        } else {
270
                                throw new IllegalArgumentException("-excludepath requires a globbing expression");
×
271
                        }
272
                } else if (arg.equals("-o")) {
4✔
273
                        if (i < args.length) {
4!
274
                                outputFileName = args[i+1].trim();
8✔
275
                                argumentsTreated++;
2✔
276
                        } else {
277
                                throw new IllegalArgumentException("-o requires a filename");
×
278
                        }
279
                } else if (arg.equals("-sysLibPath")) {
4!
NEW
280
                        if (i < args.length) {
×
NEW
281
                                pathToSystemLibrary = args[i+1].trim();
×
NEW
282
                                argumentsTreated++;
×
283
                        } else {
NEW
284
                                throw new IllegalArgumentException("-sysLibPath requires a filename");
×
285
                        }
286
                } else if (arg.equals("-i")) {
4✔
287
                        incrementalParsing = true;
4✔
288

289
                }
290
                else if (arg.equals("-jdkMode")) {
4!
291
                        parsingJdk = true;
4✔
292
                }
293
                else if (arg.equals("-debugging")) {
×
294
                        debugging = true;
×
295
                } else {
296
                        throw new IllegalArgumentException("** Unrecognized option: " + arg);
×
297
                }
298

299
                return argumentsTreated;
2✔
300
        }
301

302
        /**
303
         * Computes the path of all included jars
304
         */
305
        protected String[] setOptionClassPath( String[] classPath, String[] args, int i) throws IllegalArgumentException {
306
                if (args[i].equals("-autocp")) {
6!
307
                        if (i+1 < args.length) {
×
308
                                return addToClassPath(classPath, collectAllJars(args[i+1]) );
×
309
                        } else {
310
                                throw new IllegalArgumentException("-autocp requires a root folder");
×
311
                        }
312
                }
313
                else if (args[i].equals("-filecp")) {
6!
314
                        if (i+1 < args.length) {
×
315
                                return addToClassPath(classPath, readAllJars(args[i+1]));
×
316
                        } else {
317
                                throw new IllegalArgumentException("-filecp requires a filename");
×
318
                        }
319
                }
320
                else if (args[i].equals("-cp")) {
6!
321
                        if (i+1 < args.length) {
6!
322
                                return addToClassPath(classPath,  Arrays.asList(args[i+1].split(System.getProperty("path.separator"))));
13✔
323
                        }
324
                        else {
325
                                throw new IllegalArgumentException("-cp requires a classPath");
×
326
                        }
327
                }
328
                return classPath;
×
329
        }
330

331
        protected void setOptionEncoding(String[] args, int i) {
332
                if (i+1 < args.length) {
6✔
333
                        this.fileEncoding = args[i + 1].trim();
8✔
334
                        if (Charset.availableCharsets().get(this.fileEncoding) == null) {
5✔
335
                                throw new IllegalArgumentException("Unknown file encoding: -encoding " + this.fileEncoding);
7✔
336
                        }
337
                } else {
338
                        throw new IllegalArgumentException("-encoding requires an encoding name (eg. " + DEFAULT_FILE_ENCODING + ")");
5✔
339
                }
340
        }
1✔
341

342
        protected void setOptionAnchor(String[] args, int i) {
343
                if (i+1 < args.length) {
6!
344
                        String anchor = args[i + 1].trim();
7✔
345
                        anchors = VerveineJOptions.AnchorOptions.getValue(anchor);
4✔
346
                        if (anchors == null) {
3!
347
                                throw new IllegalArgumentException("unknown option to -anchor: " + anchor);
×
348
                        }
349
                } else {
1✔
350
                        throw new IllegalArgumentException("-anchor requires an option (none|default|assoc)");
×
351
                }
352
        }
1✔
353

354
        protected void setOptionFormat(String[] args, int i) {
355
                if (i+1 < args.length) {
6!
356
                        this.outputFormat = args[i + 1].trim();
8✔
357
                        if ((! this.outputFormat.equalsIgnoreCase(MSE_OUTPUT_FORMAT)) && (! this.outputFormat.equalsIgnoreCase(JSON_OUTPUT_FORMAT))) {
10!
358
                                throw new IllegalArgumentException("unknown option to -format: " + outputFormat);
×
359
                        }
360
                } else {
361
                        throw new IllegalArgumentException("-format requires an option (mse|json)");
×
362
                }
363
        }
1✔
364

365
        protected List<String> collectAllJars(String sDir) {
366
                File[] faFiles = new File(sDir).listFiles();
×
367
                List<String> tmpPath = new ArrayList<String>();
×
368
                for (File file : faFiles) {
×
369
                        if (file.getName().endsWith("jar")) {
×
370
                                tmpPath.add(file.getAbsolutePath());
×
371
                        }
372
                        if (file.isDirectory()) {
×
373
                                tmpPath.addAll(collectAllJars(file.getAbsolutePath()));
×
374
                        }
375
                }
376
                return tmpPath;
×
377
        }
378

379
        protected String[] addToClassPath(String[] classPath, List<String> tmpPath) {
380
                int oldlength = classPath.length;
3✔
381
                int newlength = oldlength + tmpPath.size();
5✔
382
                classPath = Arrays.copyOf(classPath, newlength);
5✔
383
                for (int p = oldlength; p < newlength; p++) {
7✔
384
                        classPath[p] = tmpPath.get(p - oldlength);
9✔
385
                }
386
                return classPath;
2✔
387
        }
388

389
        /** Reads all jar in classpath from a file, one per line
390
         * @param filename of the file containing the jars of the classpath
391
         * @return the collection of jar paths
392
         */
393
        protected List<String> readAllJars(String filename) {
394
                List<String> tmpPath = new ArrayList<String>();
×
395
                try {
396
                        BufferedReader fcp = new BufferedReader(new FileReader(filename));
×
397
                        String jarname = fcp.readLine();
×
398
                        while (jarname != null) {
×
399
                                tmpPath.add(jarname);
×
400
                                jarname = fcp.readLine();
×
401
                        }
402
                        fcp.close();
×
403
                } catch (FileNotFoundException e) {
×
404
                        System.err.println("** Error classpath file " + filename + " not found");
×
405
                        e.printStackTrace();
×
406
                } catch (IOException e) {
×
407
                        System.err.println("** Error reading classpath file: " + filename);
×
408
                        e.printStackTrace();
×
409
                }
×
410
                return tmpPath;
×
411
        }
412

413
        protected void usage() {
414
                System.err.println("Usage: VerveineJ [-h] [-i] [-o <output-file-name>] [-prettyPrint] [-summary] [-alllocals] [-anchor (none|default|assoc)] [-cp CLASSPATH | -autocp DIR] [-1.1 | -1 | -1.2 | -2 | ... | -1.7 | -7] <files-to-parse> | <dirs-to-parse>");
3✔
415
                System.err.println("      [-h] prints this message");
3✔
416
                System.err.println("      [-i] toggles incremental parsing on (can parse a project in parts that are added to the output file)");
3✔
417
                System.err.println("      [-o <output-file-name>] specifies the name of the output file (default:" + OUTPUT_FILE + ")");
3✔
418
                System.err.println("      [-format (mse|json)] specifies the output format (default:" + MSE_OUTPUT_FORMAT + ")");
3✔
419
                System.err.println("      [-prettyPrint] toggles the usage of the json pretty printer");
3✔
420
                System.err.println("      [-summary] toggles summarization of information at the level of classes.");
3✔
421
                System.err.println("                 Summarizing at the level of classes does not produce Methods, Attributes, Accesses, and Invocations");
3✔
422
                System.err.println("                 Everything is represented as references between classes: e.g. \"A.m1() invokes B.m2()\" is uplifted to \"A references B\"");
3✔
423
                System.err.println("      [-alllocals] Forces outputing all local variables, even those with primitive type (incompatible with \"-summary\")");
3✔
424
                System.err.println("      [-encoding <file-encoding-name>] File encoding to use for reading the source code default: " + DEFAULT_FILE_ENCODING);
3✔
425
                System.err.println("      [-anchor (none|entity|default|assoc)] options for source anchor information:\n" +
3✔
426
                                "                                     - no entity\n" +
427
                                "                                     - only named entities [default]\n" +
428
                                "                                     - named entities+associations (i.e. accesses, invocations, references)");
429
                System.err.println("      [-commenttext] comments text in the model instead of as a source anchor");
3✔
430
                System.err.println("      [-cp CLASSPATH] classpath where to look for stubs");
3✔
431
                System.err.println("      [-autocp DIR] gather all jars in DIR and put them in the classpath");
3✔
432
                System.err.println("      [-filecp FILE] gather all jars listed in FILE (absolute paths) and put them in the classpath");
3✔
433
                System.err.println("      [-excludepath GLOBBINGEXPR] A globbing expression of file path to exclude from parsing");
3✔
434
                System.err.println("      [-1.1 | -1 | -1.2 | -2 | ... | -1.9 | -9 | -10 | -11 | ... ] specifies version of Java");
3✔
435
                System.err.println("      [-jdkMode] option to ABSOLUTELY set if you are making a model of a JDK");
3✔
436
                System.err.println("      [-sysLibPath <path-to-runtime-jar>] path to the system library for JDT to resolve native Java binding in the parsed code");
3✔
437
                System.err.println("                                                                                By default, JDT will collect the library used to execute VVJ (unless the option -jdkMode is active).");
3✔
438
                System.err.println("      <files-to-parse>|<dirs-to-parse> list of source files to parse or directories to search for source files");
3✔
439
        }
1✔
440

441
        protected void setCodeVersion(String arg) {
442
                if (codeVers != null) {
3!
443
                        System.err.println("Trying to set twice code versions: " + codeVers + " and " + arg);
×
444
                        usage();
×
445
                        throw new IllegalArgumentException();
×
446
                } else if(VERSION_MAP.containsKey(arg)){
4!
447
                        codeVers = VERSION_MAP.get(arg);
6✔
448
                }
449

450
        }
1✔
451

452
        public String getOutputFileName() {
453
                return this.outputFileName;
3✔
454
        }
455

456
        public void configureJDTParser(ASTParser jdtParser) {
457
                // If I am parsing a JDK or providing the system library,
458
                // JDT must not fetch the VM's running libraries (=JRE used by VerveineJ at runtime)
459
                boolean includeRunningVMBootclasspath = !(parsingJdk || pathToSystemLibrary != null);
10!
460
                
461
                if (pathToSystemLibrary != null) {
3!
NEW
462
                        List<String> deps = new ArrayList<String>();
×
NEW
463
                        deps.add(pathToSystemLibrary);
×
NEW
464
                        classPathOptions = addToClassPath(classPathOptions, deps);
×
465
                }
466
                
467
                String[] sourcePathEntries = argPath.toArray(new String[0]);
7✔
468
                
469
                jdtParser.setEnvironment(classPathOptions, /*sourcepathEntries*/sourcePathEntries, /*encodings*/null, includeRunningVMBootclasspath);
7✔
470
                jdtParser.setResolveBindings(true);
3✔
471
                /**
472
                 *  Incremental parsing should not activate Binding recovery because using this option with incremental parsing
473
                 * will result in lot of stubs in the model that would have been resolved later
474
                 * */
475
                if (!incrementalParsing) {
3✔
476
                        jdtParser.setBindingsRecovery(true);
3✔
477
                }
478
                jdtParser.setKind(ASTParser.K_COMPILATION_UNIT);
3✔
479

480
                Map<String, String> javaCoreOptions = JavaCore.getOptions();
2✔
481

482
                javaCoreOptions.put(JavaCore.COMPILER_COMPLIANCE, codeVers);
6✔
483
                javaCoreOptions.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, codeVers);
6✔
484
                javaCoreOptions.put(JavaCore.COMPILER_SOURCE, codeVers);
6✔
485

486
    // Not absolutely sure it is necessary
487
                        if (pathToSystemLibrary != null)
3!
NEW
488
                                javaCoreOptions.put(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.DISABLED);
×
489
    
490
                jdtParser.setCompilerOptions(javaCoreOptions);
3✔
491

492
        }
1✔
493

494

495
        /**
496
         * Creates a regexp matcher form a globbing expression<br>
497
         * Glob to Regexp algorithm from <a href="https://stackoverflow.com/questions/1247772/is-there-an-equivalent-of-java-util-regex-for-glob-type-patterns">https://stackoverflow.com/questions/1247772/is-there-an-equivalent-of-java-util-regex-for-glob-type-patterns</a>
498
         */
499
        protected Pattern createMatcher(String expr) {
500
                expr = expr.trim();
3✔
501
                int strLen = expr.length();
3✔
502
                StringBuilder sb = new StringBuilder(strLen);
5✔
503
                sb.append('^');
4✔
504
                if (! expr.startsWith("/")) {
4!
505
                        // not absolute path, start with ".*"
506
                        if (! expr.startsWith("*")) {
4!
507
                                sb.append(".*");
×
508
                        }
509
                }
510
                boolean escaping = false;
2✔
511
                int inCurlies = 0;
2✔
512
                for (char currentChar : expr.toCharArray()) {
17✔
513
                        switch (currentChar) {
2!
514
                                case '*':
515
                                        if (escaping)
2!
516
                                                sb.append("\\*");
×
517
                                        else
518
                                                sb.append(".*");
4✔
519
                                        escaping = false;
2✔
520
                                        break;
1✔
521
                                case '?':
522
                                        if (escaping)
×
523
                                                sb.append("\\?");
×
524
                                        else
525
                                                sb.append('.');
×
526
                                        escaping = false;
×
527
                                        break;
×
528
                                case '.':
529
                                case '(':
530
                                case ')':
531
                                case '+':
532
                                case '|':
533
                                case '^':
534
                                case '$':
535
                                case '@':
536
                                case '%':
537
                                        sb.append('\\');
×
538
                                        sb.append(currentChar);
×
539
                                        escaping = false;
×
540
                                        break;
×
541
                                case '\\':
542
                                        if (escaping) {
×
543
                                                sb.append("\\\\");
×
544
                                                escaping = false;
×
545
                                        }
546
                                        else
547
                                                escaping = true;
×
548
                                        break;
×
549
                                case '{':
550
                                        if (escaping) {
×
551
                                                sb.append("\\{");
×
552
                                        }
553
                                        else {
554
                                                sb.append('(');
×
555
                                                inCurlies++;
×
556
                                        }
557
                                        escaping = false;
×
558
                                        break;
×
559
                                case '}':
560
                                        if (inCurlies > 0 && !escaping) {
×
561
                                                sb.append(')');
×
562
                                                inCurlies--;
×
563
                                        }
564
                                        else if (escaping)
×
565
                                                sb.append("\\}");
×
566
                                        else
567
                                                sb.append("}");
×
568
                                        escaping = false;
×
569
                                        break;
×
570
                                case ',':
571
                                        if (inCurlies > 0 && !escaping) {
×
572
                                                sb.append('|');
×
573
                                        }
574
                                        else if (escaping)
×
575
                                                sb.append("\\,");
×
576
                                        else
577
                                                sb.append(",");
×
578
                                        break;
×
579
                                default:
580
                                        escaping = false;
2✔
581
                                        sb.append(currentChar);
4✔
582
                        }
583
                }
584

585
                if (! expr.endsWith("*")) {
4!
586
                        sb.append(".*$");
×
587
                }
588
                else {
589
                        sb.append('$');
4✔
590
                }
591
                return Pattern.compile(sb.toString());
4✔
592
        }
593

594
        protected void collectJavaFiles(Collection<String> paths, Collection<String> files) {
595
                excludeMatchers = new ArrayList<>(excludePaths.size());
8✔
596
                for (String expr : excludePaths) {
11✔
597
                        excludeMatchers.add(createMatcher(expr));
7✔
598
                }
1✔
599
                for (String p : paths) {
10✔
600
                        collectJavaFiles(new File(p), files);
7✔
601
                }
1✔
602
        }
1✔
603

604
        protected void collectJavaFiles(File f, Collection<String> files) {
605
                for (Pattern filter : excludeMatchers) {
11✔
606
                        String absolutePath = f.getAbsolutePath();
3✔
607
                        if (filter.matcher(absolutePath).matches()) {
5✔
608
                                System.out.println("Excluded file: " + absolutePath);
4✔
609
                                return;
1✔
610
                        }
611
                }
1✔
612
                if (f.isFile() && f.getName().endsWith(".java")) {
8✔
613
                        files.add(f.getAbsolutePath());
6✔
614
                } else if (f.isDirectory()) {
3✔
615
                        for (File child : f.listFiles()) {
17✔
616
                                collectJavaFiles(child, files);
4✔
617
                        }
618
                }
619
        }
1✔
620

621
        protected String[] sourceFilesToParse() {
622
                ArrayList<String> sourceFiles = new ArrayList<String>();
4✔
623

624
                sourceFiles.addAll(argFiles);
5✔
625
                collectJavaFiles(argPath, sourceFiles);
5✔
626

627
                return sourceFiles.toArray( new String[sourceFiles.size()] );
7✔
628
        }
629

630

631
        public boolean withAnchors() {
632
                return anchors != AnchorOptions.none;
7!
633
        }
634

635
        public boolean withAnchors(AnchorOptions anchorOption) {
636
                return anchors == anchorOption;
8✔
637
        }
638

639
        public boolean withLocals() {
640
                return allLocals;
3✔
641
        }
642

643
        public boolean withDebug() {
644
                return debugging;
×
645
        }
646

647
        public boolean commentsAsText() {
648
                return commentText;
3✔
649
        }
650

651
        public boolean isParsingJdk() {
652
                return parsingJdk;
×
653
        }
654

655
        public String getFileEncoding() {
656
                return fileEncoding;
3✔
657
        }
658

659
}
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