Skip to content

Commit 3fb997b

Browse files
authored
Merge pull request #2979 from idodeclare/feature/uctags
Feature/uctags
2 parents 0f3b14d + 146d152 commit 3fb997b

File tree

18 files changed

+264
-123
lines changed

18 files changed

+264
-123
lines changed

dev/checkstyle/suppressions.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ Portions Copyright (c) 2018-2019, Chris Fraire <cfraire@me.com>.
3939
|JFlexXrefUtils\.java|FileAnalyzerFactory\.java|SearchController\.java|
4040
|Context\.java|HistoryContext\.java|Suggester\.java" />
4141

42+
<suppress checks="FileLength" files="RuntimeEnvironment\.java" />
43+
4244
<suppress checks="MethodLength" files="Indexer\.java" />
4345

4446
<suppress checks="JavadocStyle" files="MellonHeaderDecoder\.java|CustomSloppyPhraseScorer\.java|

dev/install-universal_ctags.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
git clone https://github.com/universal-ctags/ctags.git
44
cd ctags
5-
# need to use last working version until issue #2977 is resolved.
6-
git reset --hard 1295de210df49c979f27e185106a7ebc55146c57
75
./autogen.sh
86
./configure && make && make install
97
/usr/local/bin/ctags --version

opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/Ctags.java

Lines changed: 63 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.nio.charset.StandardCharsets;
3535
import java.time.Duration;
3636
import java.util.ArrayList;
37+
import java.util.Collections;
3738
import java.util.List;
3839
import java.util.concurrent.ExecutionException;
3940
import java.util.concurrent.ExecutorService;
@@ -58,20 +59,25 @@ public class Ctags implements Resettable {
5859

5960
private static final Logger LOGGER = LoggerFactory.getLogger(Ctags.class);
6061

62+
private final RuntimeEnvironment env;
6163
private volatile boolean closing;
6264
private final LangTreeMap defaultLangMap = new LangTreeMap();
6365
private LangMap langMap;
66+
private List<String> command;
6467
private Process ctags;
6568
private OutputStreamWriter ctagsIn;
6669
private BufferedReader ctagsOut;
6770
private static final String CTAGS_FILTER_TERMINATOR = "__ctags_done_with_file__";
68-
private String binary;
6971
private String CTagsExtraOptionsFile = null;
7072
private int tabSize;
7173
private Duration timeout = Duration.ofSeconds(10);
7274

7375
private boolean junit_testing = false;
7476

77+
public Ctags() {
78+
env = RuntimeEnvironment.getInstance();
79+
}
80+
7581
/**
7682
* Gets a value indicating if a subprocess of ctags was started and it is
7783
* not alive.
@@ -82,14 +88,6 @@ public boolean isClosed() {
8288
return ctags != null && !ctags.isAlive();
8389
}
8490

85-
public String getBinary() {
86-
return binary;
87-
}
88-
89-
public void setBinary(String binary) {
90-
this.binary = binary;
91-
}
92-
9391
public void setLangMap(LangMap langMap) {
9492
this.langMap = langMap;
9593
}
@@ -136,22 +134,31 @@ public void close() {
136134
}
137135
}
138136

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();
142148

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");
145152

146153
// Workaround for bug #14924: Don't get local variables in Java
147154
// code since that creates many false positives.
148155
// CtagsTest : bug14924 "too many methods" guards for this
149156
// universal ctags are however safe, so enabling for them
150-
command.add("--java-kinds=+l");
157+
command.add("--kinds-java=+l");
151158

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");
155162
command.add("--file-scope=yes");
156163
command.add("-u");
157164
command.add("--filter=yes");
@@ -201,18 +208,20 @@ private void initialize() throws IOException {
201208

202209
/* Add extra command line options for ctags. */
203210
if (CTagsExtraOptionsFile != null) {
204-
LOGGER.log(Level.INFO, "Adding extra options to ctags");
211+
LOGGER.log(Level.FINER, "Adding extra options to ctags");
205212
command.add("--options=" + CTagsExtraOptionsFile);
206213
}
214+
}
207215

216+
private void run() throws IOException {
208217
StringBuilder sb = new StringBuilder();
209218
for (String s : command) {
210219
sb.append(s).append(" ");
211220
}
212221
String commandStr = sb.toString();
213222
LOGGER.log(Level.FINE, "Executing ctags command [{0}]", commandStr);
214223

215-
processBuilder = new ProcessBuilder(command);
224+
ProcessBuilder processBuilder = new ProcessBuilder(command);
216225

217226
ctags = processBuilder.start();
218227
ctagsIn = new OutputStreamWriter(
@@ -242,7 +251,9 @@ private void initialize() throws IOException {
242251
}
243252

244253
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+
}
246257
defaultLangMap.add(".RS", "rust"); // Upper-case file spec
247258

248259
// The following are not supported yet in Universal Ctags b13cb551
@@ -256,9 +267,12 @@ private void addRustSupport(List<String> command) {
256267
}
257268

258269
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+
}
260273
defaultLangMap.add(".PS1", "powershell"); // Upper-case file spec
261274
defaultLangMap.add(".PSM1", "powershell"); // Upper-case file spec
275+
262276
command.add("--regex-powershell=/\\$(\\{[^}]+\\})/\\1/v,variable/");
263277
command.add("--regex-powershell=/\\$([[:alnum:]_]+([:.][[:alnum:]_]+)*)/\\1/v,variable/");
264278
command.add("--regex-powershell=/^[[:space:]]*(:[^[:space:]]+)/\\1/l,label/");
@@ -275,8 +289,11 @@ private void addPowerShellSupport(List<String> command) {
275289
}
276290

277291
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+
}
279295
defaultLangMap.add(".PAS", "pascal"); // Upper-case file spec
296+
280297
command.add("--regex-pascal=/([[:alnum:]_]+)[[:space:]]*=[[:space:]]*\\([[:space:]]*[[:alnum:]_][[:space:]]*\\)/\\1/t,Type/");
281298
command.add("--regex-pascal=/([[:alnum:]_]+)[[:space:]]*=[[:space:]]*class[[:space:]]*[^;]*$/\\1/c,Class/");
282299
command.add("--regex-pascal=/([[:alnum:]_]+)[[:space:]]*=[[:space:]]*interface[[:space:]]*[^;]*$/\\1/i,interface/");
@@ -290,7 +307,9 @@ private void addPascalSupport(List<String> command) {
290307
}
291308

292309
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+
}
294313
defaultLangMap.add(".SWIFT", "swift"); // Upper-case file spec
295314
command.add("--regex-swift=/enum[[:space:]]+([^\\{\\}]+).*$/\\1/n,enum,enums/");
296315
command.add("--regex-swift=/typealias[[:space:]]+([^:=]+).*$/\\1/t,typealias,typealiases/");
@@ -303,9 +322,12 @@ private void addSwiftSupport(List<String> command) {
303322
}
304323

305324
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+
}
307328
defaultLangMap.add(".KT", "kotlin"); // Upper-case file spec
308329
defaultLangMap.add(".KTS", "kotlin"); // Upper-case file spec
330+
309331
command.add("--regex-kotlin=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
310332
"(private[^ ]*|protected)?[[:space:]]*class[[:space:]]+([[:alnum:]_:]+)/\\4/c,classes/");
311333
command.add("--regex-kotlin=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
@@ -326,8 +348,13 @@ private void addKotlinSupport(List<String> command) {
326348
command.add("--regex-kotlin=/^[[:space:]]*import[[:space:]]+([[:alnum:]_.:]+)/\\1/I,imports/");
327349
}
328350

351+
/**
352+
* Override Clojure support with patterns from https://gist.github.com/kul/8704283.
353+
*/
329354
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+
}
331358
defaultLangMap.add(".CLJ", "clojure"); // Upper-case file spec
332359
defaultLangMap.add(".CLJS", "clojure"); // Upper-case file spec
333360
defaultLangMap.add(".CLJX", "clojure"); // Upper-case file spec
@@ -345,9 +372,12 @@ private void addClojureSupport(List<String> command) {
345372
}
346373

347374
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+
}
349378
defaultLangMap.add(".HS", "haskell"); // Upper-case file spec
350379
defaultLangMap.add(".HSC", "haskell"); // Upper-case file spec
380+
351381
command.add("--regex-haskell=/^[[:space:]]*class[[:space:]]+([a-zA-Z0-9_]+)/\\1/c,classes/");
352382
command.add("--regex-haskell=/^[[:space:]]*data[[:space:]]+([a-zA-Z0-9_]+)/\\1/t,types/");
353383
command.add("--regex-haskell=/^[[:space:]]*newtype[[:space:]]+([a-zA-Z0-9_]+)/\\1/t,types/");
@@ -359,8 +389,11 @@ private void addHaskellSupport(List<String> command) {
359389
}
360390

361391
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+
}
363395
defaultLangMap.add(".SCALA", "scala"); // Upper-case file spec
396+
364397
command.add("--regex-scala=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
365398
"(private|protected)?[[:space:]]*class[[:space:]]+([a-zA-Z0-9_]+)/\\4/c,classes/");
366399
command.add("--regex-scala=/^[[:space:]]*((abstract|final|sealed|implicit|lazy)[[:space:]]*)*" +
@@ -408,6 +441,7 @@ public Definitions doCtags(String file) throws IOException,
408441
}
409442
} else {
410443
initialize();
444+
run();
411445
}
412446

413447
CtagsReader rdr = new CtagsReader();
@@ -429,7 +463,7 @@ public Definitions doCtags(String file) throws IOException,
429463
* the ctags process completes so that the indexer can
430464
* make progress instead of hanging the whole operation.
431465
*/
432-
IndexerParallelizer parallelizer = RuntimeEnvironment.getInstance().getIndexerParallelizer();
466+
IndexerParallelizer parallelizer = env.getIndexerParallelizer();
433467
ExecutorService executor = parallelizer.getCtagsWatcherExecutor();
434468
Future<Definitions> future = executor.submit(() -> {
435469
readTags(rdr);

opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/swift/SwiftAnalyzer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ protected SwiftAnalyzer(AnalyzerFactory factory) {
4646
}
4747

4848
/**
49-
* @return {@code "Swift"} to match the OpenGrok-customized definitions
49+
* @return {@code "swift"} to match the OpenGrok-customized definitions
5050
*/
5151
@Override
5252
public String getCtagsLang() {
53-
return "Swift";
53+
return "swift";
5454
}
5555

5656
/**

opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/RuntimeEnvironment.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.ArrayList;
3535
import java.util.Collections;
3636
import java.util.Date;
37+
import java.util.HashSet;
3738
import java.util.List;
3839
import java.util.Map;
3940
import java.util.Set;
@@ -121,6 +122,11 @@ public final class RuntimeEnvironment {
121122

122123
private transient File dtagsEftar = null;
123124

125+
private transient volatile Boolean ctagsFound;
126+
private final transient Set<String> ctagsLanguages = new HashSet<>();
127+
128+
public WatchDogService watchDog;
129+
124130
/**
125131
* Creates a new instance of RuntimeEnvironment. Private to ensure a
126132
* singleton anti-pattern.
@@ -180,8 +186,6 @@ public static RuntimeEnvironment getInstance() {
180186
return instance;
181187
}
182188

183-
public WatchDogService watchDog;
184-
185189
public IndexerParallelizer getIndexerParallelizer() {
186190
return lzIndexerParallelizer.get();
187191
}
@@ -641,24 +645,42 @@ public void setHitsPerPage(int hitsPerPage) {
641645
setConfigurationValue("hitsPerPage", hitsPerPage);
642646
}
643647

644-
private transient Boolean ctagsFound;
645-
646648
/**
647649
* Validate that there is a Universal ctags program.
648650
*
649651
* @return true if success, false otherwise
650652
*/
651653
public boolean validateUniversalCtags() {
652654
if (ctagsFound == null) {
653-
if (!CtagsUtil.validate(getCtags())) {
654-
ctagsFound = false;
655-
} else {
656-
ctagsFound = true;
655+
String ctagsBinary = getCtags();
656+
configLock.writeLock().lock();
657+
try {
658+
if (ctagsFound == null) {
659+
ctagsFound = CtagsUtil.validate(ctagsBinary);
660+
if (ctagsFound) {
661+
List<String> languages = CtagsUtil.getLanguages(ctagsBinary);
662+
if (languages != null) {
663+
ctagsLanguages.addAll(languages);
664+
}
665+
}
666+
}
667+
} finally {
668+
configLock.writeLock().unlock();
657669
}
658670
}
659671
return ctagsFound;
660672
}
661673

674+
/**
675+
* Gets the base set of supported Ctags languages.
676+
* @return a defined set which may be empty if
677+
* {@link #validateUniversalCtags()} has not yet been called or if the call
678+
* fails
679+
*/
680+
public Set<String> getCtagsLanguages() {
681+
return Collections.unmodifiableSet(ctagsLanguages);
682+
}
683+
662684
/**
663685
* Get the max time a SCM operation may use to avoid being cached.
664686
*

opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexDatabase.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -742,9 +742,7 @@ private void addFile(File file, String path, Ctags ctags)
742742
if (env.getCtagsTimeout() != 0) {
743743
ctags.setTimeout(env.getCtagsTimeout());
744744
}
745-
if (ctags.getBinary() != null) {
746-
fa.setCtags(ctags);
747-
}
745+
fa.setCtags(ctags);
748746
fa.setProject(Project.getProject(path));
749747
fa.setScopesEnabled(env.isScopesEnabled());
750748
fa.setFoldingEnabled(env.isFoldingEnabled());

0 commit comments

Comments
 (0)