34
34
import java .nio .charset .StandardCharsets ;
35
35
import java .time .Duration ;
36
36
import java .util .ArrayList ;
37
+ import java .util .Collections ;
37
38
import java .util .List ;
38
39
import java .util .concurrent .ExecutionException ;
39
40
import java .util .concurrent .ExecutorService ;
@@ -58,20 +59,25 @@ public class Ctags implements Resettable {
58
59
59
60
private static final Logger LOGGER = LoggerFactory .getLogger (Ctags .class );
60
61
62
+ private final RuntimeEnvironment env ;
61
63
private volatile boolean closing ;
62
64
private final LangTreeMap defaultLangMap = new LangTreeMap ();
63
65
private LangMap langMap ;
66
+ private List <String > command ;
64
67
private Process ctags ;
65
68
private OutputStreamWriter ctagsIn ;
66
69
private BufferedReader ctagsOut ;
67
70
private static final String CTAGS_FILTER_TERMINATOR = "__ctags_done_with_file__" ;
68
- private String binary ;
69
71
private String CTagsExtraOptionsFile = null ;
70
72
private int tabSize ;
71
73
private Duration timeout = Duration .ofSeconds (10 );
72
74
73
75
private boolean junit_testing = false ;
74
76
77
+ public Ctags () {
78
+ env = RuntimeEnvironment .getInstance ();
79
+ }
80
+
75
81
/**
76
82
* Gets a value indicating if a subprocess of ctags was started and it is
77
83
* not alive.
@@ -82,14 +88,6 @@ public boolean isClosed() {
82
88
return ctags != null && !ctags .isAlive ();
83
89
}
84
90
85
- public String getBinary () {
86
- return binary ;
87
- }
88
-
89
- public void setBinary (String binary ) {
90
- this .binary = binary ;
91
- }
92
-
93
91
public void setLangMap (LangMap langMap ) {
94
92
this .langMap = langMap ;
95
93
}
@@ -136,22 +134,31 @@ public void close() {
136
134
}
137
135
}
138
136
139
- private void initialize () throws IOException {
140
- ProcessBuilder processBuilder ;
141
- List <String > command = new ArrayList <>();
137
+ /**
138
+ * Gets the command-line arguments used to run ctags.
139
+ * @return a defined (immutable) list
140
+ */
141
+ public List <String > getArgv () {
142
+ initialize ();
143
+ return Collections .unmodifiableList (command );
144
+ }
145
+
146
+ private void initialize () {
147
+ env .validateUniversalCtags ();
142
148
143
- command .add (binary );
144
- command .add ("--c-kinds=+l" );
149
+ command = new ArrayList <>();
150
+ command .add (env .getCtags ());
151
+ command .add ("--kinds-c=+l" );
145
152
146
153
// Workaround for bug #14924: Don't get local variables in Java
147
154
// code since that creates many false positives.
148
155
// CtagsTest : bug14924 "too many methods" guards for this
149
156
// universal ctags are however safe, so enabling for them
150
- command .add ("--java- kinds=+l" );
157
+ command .add ("--kinds-java =+l" );
151
158
152
- command .add ("--sql- kinds=+l" );
153
- command .add ("--Fortran- kinds=+L" );
154
- command .add ("--C++-kinds =+l" );
159
+ command .add ("--kinds-sql =+l" );
160
+ command .add ("--kinds-Fortran =+L" );
161
+ command .add ("--kinds- C++=+l" );
155
162
command .add ("--file-scope=yes" );
156
163
command .add ("-u" );
157
164
command .add ("--filter=yes" );
@@ -201,18 +208,20 @@ private void initialize() throws IOException {
201
208
202
209
/* Add extra command line options for ctags. */
203
210
if (CTagsExtraOptionsFile != null ) {
204
- LOGGER .log (Level .INFO , "Adding extra options to ctags" );
211
+ LOGGER .log (Level .FINER , "Adding extra options to ctags" );
205
212
command .add ("--options=" + CTagsExtraOptionsFile );
206
213
}
214
+ }
207
215
216
+ private void run () throws IOException {
208
217
StringBuilder sb = new StringBuilder ();
209
218
for (String s : command ) {
210
219
sb .append (s ).append (" " );
211
220
}
212
221
String commandStr = sb .toString ();
213
222
LOGGER .log (Level .FINE , "Executing ctags command [{0}]" , commandStr );
214
223
215
- processBuilder = new ProcessBuilder (command );
224
+ ProcessBuilder processBuilder = new ProcessBuilder (command );
216
225
217
226
ctags = processBuilder .start ();
218
227
ctagsIn = new OutputStreamWriter (
@@ -242,7 +251,9 @@ private void initialize() throws IOException {
242
251
}
243
252
244
253
private void addRustSupport (List <String > command ) {
245
- command .add ("--langdef=rust" );
254
+ if (!env .getCtagsLanguages ().contains ("Rust" )) { // Built-in would be capitalized.
255
+ command .add ("--langdef=rust" ); // Lower-case if user-defined.
256
+ }
246
257
defaultLangMap .add (".RS" , "rust" ); // Upper-case file spec
247
258
248
259
// The following are not supported yet in Universal Ctags b13cb551
@@ -256,9 +267,12 @@ private void addRustSupport(List<String> command) {
256
267
}
257
268
258
269
private void addPowerShellSupport (List <String > command ) {
259
- command .add ("--langdef=powershell" );
270
+ if (!env .getCtagsLanguages ().contains ("PowerShell" )) { // Built-in would be capitalized.
271
+ command .add ("--langdef=powershell" ); // Lower-case if user-defined.
272
+ }
260
273
defaultLangMap .add (".PS1" , "powershell" ); // Upper-case file spec
261
274
defaultLangMap .add (".PSM1" , "powershell" ); // Upper-case file spec
275
+
262
276
command .add ("--regex-powershell=/\\ $(\\ {[^}]+\\ })/\\ 1/v,variable/" );
263
277
command .add ("--regex-powershell=/\\ $([[:alnum:]_]+([:.][[:alnum:]_]+)*)/\\ 1/v,variable/" );
264
278
command .add ("--regex-powershell=/^[[:space:]]*(:[^[:space:]]+)/\\ 1/l,label/" );
@@ -275,8 +289,11 @@ private void addPowerShellSupport(List<String> command) {
275
289
}
276
290
277
291
private void addPascalSupport (List <String > command ) {
278
- command .add ("--langdef=pascal" );
292
+ if (!env .getCtagsLanguages ().contains ("Pascal" )) { // Built-in would be capitalized.
293
+ command .add ("--langdef=pascal" ); // Lower-case if user-defined.
294
+ }
279
295
defaultLangMap .add (".PAS" , "pascal" ); // Upper-case file spec
296
+
280
297
command .add ("--regex-pascal=/([[:alnum:]_]+)[[:space:]]*=[[:space:]]*\\ ([[:space:]]*[[:alnum:]_][[:space:]]*\\ )/\\ 1/t,Type/" );
281
298
command .add ("--regex-pascal=/([[:alnum:]_]+)[[:space:]]*=[[:space:]]*class[[:space:]]*[^;]*$/\\ 1/c,Class/" );
282
299
command .add ("--regex-pascal=/([[:alnum:]_]+)[[:space:]]*=[[:space:]]*interface[[:space:]]*[^;]*$/\\ 1/i,interface/" );
@@ -290,7 +307,9 @@ private void addPascalSupport(List<String> command) {
290
307
}
291
308
292
309
private void addSwiftSupport (List <String > command ) {
293
- command .add ("--langdef=swift" );
310
+ if (!env .getCtagsLanguages ().contains ("Swift" )) { // Built-in would be capitalized.
311
+ command .add ("--langdef=swift" ); // Lower-case if user-defined.
312
+ }
294
313
defaultLangMap .add (".SWIFT" , "swift" ); // Upper-case file spec
295
314
command .add ("--regex-swift=/enum[[:space:]]+([^\\ {\\ }]+).*$/\\ 1/n,enum,enums/" );
296
315
command .add ("--regex-swift=/typealias[[:space:]]+([^:=]+).*$/\\ 1/t,typealias,typealiases/" );
@@ -303,9 +322,12 @@ private void addSwiftSupport(List<String> command) {
303
322
}
304
323
305
324
private void addKotlinSupport (List <String > command ) {
306
- command .add ("--langdef=kotlin" );
325
+ if (!env .getCtagsLanguages ().contains ("Kotlin" )) { // Built-in would be capitalized.
326
+ command .add ("--langdef=kotlin" ); // Lower-case if user-defined.
327
+ }
307
328
defaultLangMap .add (".KT" , "kotlin" ); // Upper-case file spec
308
329
defaultLangMap .add (".KTS" , "kotlin" ); // Upper-case file spec
330
+
309
331
command .add ("--regex-kotlin=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
310
332
"(private[^ ]*|protected)?[[:space:]]*class[[:space:]]+([[:alnum:]_:]+)/\\ 4/c,classes/" );
311
333
command .add ("--regex-kotlin=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
@@ -326,8 +348,13 @@ private void addKotlinSupport(List<String> command) {
326
348
command .add ("--regex-kotlin=/^[[:space:]]*import[[:space:]]+([[:alnum:]_.:]+)/\\ 1/I,imports/" );
327
349
}
328
350
351
+ /**
352
+ * Override Clojure support with patterns from https://gist.github.com/kul/8704283.
353
+ */
329
354
private void addClojureSupport (List <String > command ) {
330
- command .add ("--langdef=clojure" ); // clojure support (patterns are from https://gist.github.com/kul/8704283)
355
+ if (!env .getCtagsLanguages ().contains ("Clojure" )) { // Built-in would be capitalized.
356
+ command .add ("--langdef=clojure" ); // Lower-case if user-defined.
357
+ }
331
358
defaultLangMap .add (".CLJ" , "clojure" ); // Upper-case file spec
332
359
defaultLangMap .add (".CLJS" , "clojure" ); // Upper-case file spec
333
360
defaultLangMap .add (".CLJX" , "clojure" ); // Upper-case file spec
@@ -345,9 +372,12 @@ private void addClojureSupport(List<String> command) {
345
372
}
346
373
347
374
private void addHaskellSupport (List <String > command ) {
348
- command .add ("--langdef=haskell" ); // below was added with #912
375
+ if (!env .getCtagsLanguages ().contains ("Haskell" )) { // Built-in would be capitalized.
376
+ command .add ("--langdef=haskell" ); // below added with #912. Lowercase if user-defined.
377
+ }
349
378
defaultLangMap .add (".HS" , "haskell" ); // Upper-case file spec
350
379
defaultLangMap .add (".HSC" , "haskell" ); // Upper-case file spec
380
+
351
381
command .add ("--regex-haskell=/^[[:space:]]*class[[:space:]]+([a-zA-Z0-9_]+)/\\ 1/c,classes/" );
352
382
command .add ("--regex-haskell=/^[[:space:]]*data[[:space:]]+([a-zA-Z0-9_]+)/\\ 1/t,types/" );
353
383
command .add ("--regex-haskell=/^[[:space:]]*newtype[[:space:]]+([a-zA-Z0-9_]+)/\\ 1/t,types/" );
@@ -359,8 +389,11 @@ private void addHaskellSupport(List<String> command) {
359
389
}
360
390
361
391
private void addScalaSupport (List <String > command ) {
362
- command .add ("--langdef=scala" ); // below is bug 61 to get full scala support
392
+ if (!env .getCtagsLanguages ().contains ("Scala" )) { // Built-in would be capitalized.
393
+ command .add ("--langdef=scala" ); // below is bug 61 to get full scala support. Lower-case
394
+ }
363
395
defaultLangMap .add (".SCALA" , "scala" ); // Upper-case file spec
396
+
364
397
command .add ("--regex-scala=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
365
398
"(private|protected)?[[:space:]]*class[[:space:]]+([a-zA-Z0-9_]+)/\\ 4/c,classes/" );
366
399
command .add ("--regex-scala=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
@@ -408,6 +441,7 @@ public Definitions doCtags(String file) throws IOException,
408
441
}
409
442
} else {
410
443
initialize ();
444
+ run ();
411
445
}
412
446
413
447
CtagsReader rdr = new CtagsReader ();
@@ -429,7 +463,7 @@ public Definitions doCtags(String file) throws IOException,
429
463
* the ctags process completes so that the indexer can
430
464
* make progress instead of hanging the whole operation.
431
465
*/
432
- IndexerParallelizer parallelizer = RuntimeEnvironment . getInstance () .getIndexerParallelizer ();
466
+ IndexerParallelizer parallelizer = env .getIndexerParallelizer ();
433
467
ExecutorService executor = parallelizer .getCtagsWatcherExecutor ();
434
468
Future <Definitions > future = executor .submit (() -> {
435
469
readTags (rdr );
0 commit comments