Skip to content

Commit c5ef7ff

Browse files
idodeclareVladimir Kotal
authored andcommitted
Resolve #2613 : support HCL and a Terraform derivation
1 parent 2321e18 commit c5ef7ff

26 files changed

+2491
-41
lines changed

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

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
/*
2121
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
22-
* Portions Copyright (c) 2017-2019, Chris Fraire <[email protected]>.
22+
* Portions Copyright (c) 2017-2020, Chris Fraire <[email protected]>.
2323
*/
2424
package org.opengrok.indexer.analysis;
2525

@@ -30,7 +30,6 @@
3030
import java.io.InputStream;
3131
import java.io.InputStreamReader;
3232
import java.io.Reader;
33-
import java.io.StringReader;
3433
import java.io.Writer;
3534
import java.lang.reflect.InvocationTargetException;
3635
import java.nio.charset.StandardCharsets;
@@ -80,6 +79,7 @@
8079
import org.opengrok.indexer.analysis.fortran.FortranAnalyzerFactory;
8180
import org.opengrok.indexer.analysis.golang.GolangAnalyzerFactory;
8281
import org.opengrok.indexer.analysis.haskell.HaskellAnalyzerFactory;
82+
import org.opengrok.indexer.analysis.hcl.HCLAnalyzerFactory;
8383
import org.opengrok.indexer.analysis.java.JavaAnalyzerFactory;
8484
import org.opengrok.indexer.analysis.javascript.JavaScriptAnalyzerFactory;
8585
import org.opengrok.indexer.analysis.json.JsonAnalyzerFactory;
@@ -101,6 +101,7 @@
101101
import org.opengrok.indexer.analysis.sql.SQLAnalyzerFactory;
102102
import org.opengrok.indexer.analysis.swift.SwiftAnalyzerFactory;
103103
import org.opengrok.indexer.analysis.tcl.TclAnalyzerFactory;
104+
import org.opengrok.indexer.analysis.terraform.TerraformAnalyzerFactory;
104105
import org.opengrok.indexer.analysis.typescript.TypeScriptAnalyzerFactory;
105106
import org.opengrok.indexer.analysis.uue.UuencodeAnalyzerFactory;
106107
import org.opengrok.indexer.analysis.vb.VBAnalyzerFactory;
@@ -221,8 +222,6 @@ public class AnalyzerGuru {
221222
*/
222223
private static final List<String> analysisPkgNames = new ArrayList<>();
223224

224-
public static final Reader dummyR = new StringReader("");
225-
public static final String dummyS = "";
226225
public static final FieldType string_ft_stored_nanalyzed_norms = new FieldType(StringField.TYPE_STORED);
227226
public static final FieldType string_ft_nstored_nanalyzed_norms = new FieldType(StringField.TYPE_NOT_STORED);
228227

@@ -300,7 +299,9 @@ public class AnalyzerGuru {
300299
new EiffelAnalyzerFactory(),
301300
new VerilogAnalyzerFactory(),
302301
new TypeScriptAnalyzerFactory(),
303-
new AsmAnalyzerFactory()
302+
new AsmAnalyzerFactory(),
303+
new HCLAnalyzerFactory(),
304+
new TerraformAnalyzerFactory()
304305
};
305306

306307
for (AnalyzerFactory analyzer : analyzers) {
@@ -334,15 +335,15 @@ public class AnalyzerGuru {
334335
* {@link FileAnalyzerFactory} subclasses are revised to target more or
335336
* different files.
336337
* @return a value whose lower 32-bits are a static value
337-
* 20191120_00
338+
* 20200410_00
338339
* for the current implementation and whose higher-32 bits are non-zero if
339340
* {@link #addExtension(java.lang.String, AnalyzerFactory)}
340341
* or
341342
* {@link #addPrefix(java.lang.String, AnalyzerFactory)}
342343
* has been called.
343344
*/
344345
public static long getVersionNo() {
345-
final int ver32 = 20191120_00; // Edit comment above too!
346+
final int ver32 = 20200410_00; // Edit comment above too!
346347
long ver = ver32;
347348
if (customizationHashCode != 0) {
348349
ver |= (long) customizationHashCode << 32;
@@ -633,26 +634,6 @@ public void populateDocument(Document doc, File file, String path,
633634
}
634635
}
635636

636-
/**
637-
* Get the content type for a named file.
638-
*
639-
* @param in The input stream we want to get the content type for (if we
640-
* cannot determine the content type by the filename)
641-
* @param file The name of the file
642-
* @return The contentType suitable for printing to
643-
* response.setContentType() or null if the factory was not found
644-
* @throws java.io.IOException If an error occurs while accessing the input
645-
* stream.
646-
*/
647-
public static String getContentType(InputStream in, String file) throws IOException {
648-
AnalyzerFactory factory = find(in, file);
649-
String type = null;
650-
if (factory != null) {
651-
type = factory.getContentType();
652-
}
653-
return type;
654-
}
655-
656637
/**
657638
* Write a browse-able version of the file.
658639
*
@@ -780,7 +761,7 @@ public static AnalyzerFactory findByFileTypeName(String fileTypeName) {
780761
public static AnalyzerFactory findFactory(String factoryClassName)
781762
throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException,
782763
InvocationTargetException {
783-
Class<?> fcn = null;
764+
Class<?> fcn;
784765
try {
785766
fcn = Class.forName(factoryClassName);
786767

@@ -1031,9 +1012,7 @@ private static AnalyzerFactory findForStream(InputStream in,
10311012
return null;
10321013
}
10331014

1034-
private static AnalyzerFactory findMagicString(String opening,
1035-
String file)
1036-
throws IOException {
1015+
private static AnalyzerFactory findMagicString(String opening, String file) {
10371016

10381017
// first, try to look up two words in magics
10391018
String fragment = getWords(opening, 2);
@@ -1207,6 +1186,6 @@ private static boolean factoriesDifferent(AnalyzerFactory a,
12071186
if (a_name == null && b_name == null) {
12081187
return false;
12091188
}
1210-
return a_name == null || b_name == null || !a_name.equals(b_name);
1189+
return a_name == null || !a_name.equals(b_name);
12111190
}
12121191
}

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

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
/*
2121
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
22-
* Portions Copyright (c) 2017-2019, Chris Fraire <[email protected]>.
22+
* Portions Copyright (c) 2017-2020, Chris Fraire <[email protected]>.
2323
*/
2424
package org.opengrok.indexer.analysis;
2525

@@ -185,22 +185,15 @@ private void initialize() {
185185
//on Solaris regexp.h used is different than on linux (gnu regexp)
186186
//http://en.wikipedia.org/wiki/Regular_expression#POSIX_basic_and_extended
187187
addScalaSupport(command);
188-
189188
addHaskellSupport(command);
190-
191189
//temporarily use our defs until ctags will fix https://github.com/universal-ctags/ctags/issues/988
192190
addClojureSupport(command);
193-
194191
addKotlinSupport(command);
195-
196192
addSwiftSupport(command);
197-
198193
addRustSupport(command);
199-
200194
addPascalSupport(command);
201-
202195
addPowerShellSupport(command);
203-
196+
addTerraformSupport(command);
204197
//PLEASE add new languages ONLY with POSIX syntax (see above wiki link)
205198

206199
if (langMap == null) {
@@ -401,6 +394,30 @@ private void addScalaSupport(List<String> command) {
401394
command.add("--regex-scala=/^[[:space:]]*package[[:space:]]+([a-zA-Z0-9_.]+)/\\1/p,packages/");
402395
}
403396

397+
private void addTerraformSupport(List<String> command) {
398+
if (!env.getCtagsLanguages().contains("Terraform")) { // Built-in would be capitalized.
399+
command.add("--langdef=terraform"); // Lower-case if user-defined.
400+
}
401+
402+
/*
403+
* Ignore Terraform single-line comments with short-form (only two
404+
* separators following the pattern), exclusive matches.
405+
*/
406+
command.add("--regex-terraform=,^[[:space:]]*#,,{exclusive}");
407+
command.add("--regex-terraform=,^[[:space:]]*//,,{exclusive}");
408+
409+
/*
410+
* Terraform "resource block declares a resource of a given type ...
411+
* with a given local name...." Unfortunately there is no Posix
412+
* equivalent of {Identifier} from HCL.lexh, so we must approximate with
413+
* the possibility of leaving out some matches.
414+
*/
415+
command.add("--regex-terraform=" +
416+
"/[[:<:]]resource[[:space:]]*\"([[:alpha:]][-_[:alpha:]]*)\"[[:space:]]*" +
417+
"\"([[:alpha:]][-_[:alpha:]]*)\"[[:space:]]*\\{/" +
418+
"\\1.\\2/s,struct,resource names/");
419+
}
420+
404421
/**
405422
* Run ctags on a file.
406423
* @param file file path to process
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2020, Chris Fraire <[email protected]>.
22+
*/
23+
24+
package org.opengrok.indexer.analysis.hcl;
25+
26+
import java.util.Collections;
27+
import java.util.HashSet;
28+
import java.util.Set;
29+
30+
/**
31+
* Represents a container for HCL keywords and other string constants.
32+
*/
33+
public class Consts {
34+
35+
private static final Set<String> kwd = new HashSet<>();
36+
37+
public static final Set<String> KEYWORDS = Collections.unmodifiableSet(kwd);
38+
39+
static {
40+
/*
41+
* HCL has the irritating aspect that "there are no globally-reserved
42+
* words, but in some contexts certain identifiers are reserved to
43+
* function as keywords."
44+
*
45+
* We'll just treat the following as globally reserved and wait to see
46+
* if that causes problems for any users.
47+
*/
48+
49+
kwd.add("false");
50+
kwd.add("true");
51+
kwd.add("null");
52+
kwd.add("for");
53+
kwd.add("endfor");
54+
kwd.add("in");
55+
kwd.add("if");
56+
kwd.add("else");
57+
kwd.add("endif");
58+
}
59+
60+
/* private to enforce static */
61+
private Consts() {
62+
}
63+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2017-2020, Chris Fraire <[email protected]>.
23+
*/
24+
25+
package org.opengrok.indexer.analysis.hcl;
26+
27+
import org.opengrok.indexer.analysis.AbstractAnalyzer;
28+
import org.opengrok.indexer.analysis.AnalyzerFactory;
29+
import org.opengrok.indexer.analysis.JFlexTokenizer;
30+
import org.opengrok.indexer.analysis.JFlexXref;
31+
import org.opengrok.indexer.analysis.plain.AbstractSourceCodeAnalyzer;
32+
33+
import java.io.Reader;
34+
35+
/**
36+
* Represents an extension of {@link AbstractSourceCodeAnalyzer} for the HCL
37+
* configuration language.
38+
*/
39+
public class HCLAnalyzer extends AbstractSourceCodeAnalyzer {
40+
41+
/**
42+
* Creates a new instance of {@link HCLAnalyzer}.
43+
* @param factory defined instance for the analyzer
44+
*/
45+
protected HCLAnalyzer(AnalyzerFactory factory) {
46+
super(factory, () -> new JFlexTokenizer(new HCLSymbolTokenizer(
47+
AbstractAnalyzer.DUMMY_READER)));
48+
}
49+
50+
/**
51+
* @return {@code null} as there is no aligned language
52+
*/
53+
@Override
54+
public String getCtagsLang() {
55+
return null;
56+
}
57+
58+
/**
59+
* Gets a version number to be used to tag processed documents so that
60+
* re-analysis can be re-done later if a stored version number is different
61+
* from the current implementation.
62+
* @return 20200409_05
63+
*/
64+
@Override
65+
protected int getSpecializedVersionNo() {
66+
return 20200409_05; // Edit comment above too!
67+
}
68+
69+
/**
70+
* Creates a wrapped instance of {@link HCLXref}.
71+
* @param reader an instance passed to the new {@link HCLXref}
72+
* @return a defined instance
73+
*/
74+
@Override
75+
protected JFlexXref newXref(Reader reader) {
76+
return new JFlexXref(new HCLXref(reader));
77+
}
78+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
22+
* Portions Copyright (c) 2017, 2020, Chris Fraire <[email protected]>.
23+
*/
24+
25+
package org.opengrok.indexer.analysis.hcl;
26+
27+
import org.opengrok.indexer.analysis.AbstractAnalyzer;
28+
import org.opengrok.indexer.analysis.FileAnalyzerFactory;
29+
30+
/**
31+
* Represents an extension of {@link FileAnalyzerFactory} to produce
32+
* {@link HCLAnalyzer} instances.
33+
*/
34+
public class HCLAnalyzerFactory extends FileAnalyzerFactory {
35+
36+
private static final String name = "HCL";
37+
38+
private static final String[] SUFFIXES = {"HCL"};
39+
40+
/**
41+
* Creates a new instance of {@link HCLAnalyzerFactory}.
42+
*/
43+
public HCLAnalyzerFactory() {
44+
super(null, null, SUFFIXES, null, null, "text/plain", AbstractAnalyzer.Genre.PLAIN, name);
45+
}
46+
47+
/**
48+
* Creates a new instance of {@link HCLAnalyzer}.
49+
* @return the new instance
50+
*/
51+
@Override
52+
protected AbstractAnalyzer newAnalyzer() {
53+
return new HCLAnalyzer(this);
54+
}
55+
}

0 commit comments

Comments
 (0)