1010import com .semmle .ts .extractor .TypeExtractor ;
1111import com .semmle .ts .extractor .TypeTable ;
1212import com .semmle .util .data .StringUtil ;
13+ import com .semmle .util .exception .CatastrophicError ;
1314import com .semmle .util .exception .Exceptions ;
1415import com .semmle .util .exception .ResourceError ;
1516import com .semmle .util .exception .UserError ;
2324import java .io .File ;
2425import java .io .IOException ;
2526import java .io .Reader ;
27+ import java .lang .ProcessBuilder .Redirect ;
2628import java .net .URI ;
2729import java .net .URISyntaxException ;
2830import java .nio .charset .StandardCharsets ;
6870 * patterns that can be used to refine the list of files to include and exclude
6971 * <li><code>LGTM_INDEX_TYPESCRIPT</code>: whether to extract TypeScript
7072 * <li><code>LGTM_INDEX_FILETYPES</code>: a newline-separated list of ".extension:filetype" pairs
71- * specifying which {@link FileType} to use for the given extension
73+ * specifying which {@link FileType} to use for the given extension; the additional file
74+ * type <code>XML</code> is also supported
75+ * <li><code>LGTM_INDEX_XML_MODE</code>: whether to extract XML files
7276 * <li><code>LGTM_THREADS</code>: the maximum number of files to extract in parallel
7377 * <li><code>LGTM_TRAP_CACHE</code>: the path of a directory to use for trap caching
7478 * <li><code>LGTM_TRAP_CACHE_BOUND</code>: the size to bound the trap cache to
158162 * <p>The file type as which a file is extracted can be customised via the <code>
159163 * LGTM_INDEX_FILETYPES</code> environment variable explained above.
160164 *
165+ * <p>If <code>LGTM_INDEX_XML_MODE</code> is set to <code>ALL</code>, then all files with extension
166+ * <code>.xml</code> under <code>LGTM_SRC</code> are extracted as XML (in addition to any files
167+ * whose file type is specified to be <code>XML</code> via <code>LGTM_INDEX_SOURCE_TYPE</code>).
168+ * Currently XML extraction does not respect inclusion and exclusion filters, but this is a bug,
169+ * not a feature, and hence will change eventually.
170+ *
161171 * <p>Note that all these customisations only apply to <code>LGTM_SRC</code>. Extraction of externs
162172 * is not customisable.
163173 *
@@ -178,6 +188,7 @@ public class AutoBuild {
178188 private final Map <String , FileType > fileTypes = new LinkedHashMap <>();
179189 private final Set <Path > includes = new LinkedHashSet <>();
180190 private final Set <Path > excludes = new LinkedHashSet <>();
191+ private final Set <String > xmlExtensions = new LinkedHashSet <>();
181192 private ProjectLayout filters ;
182193 private final Path LGTM_SRC , SEMMLE_DIST ;
183194 private final TypeScriptMode typeScriptMode ;
@@ -193,6 +204,7 @@ public AutoBuild() {
193204 getEnumFromEnvVar ("LGTM_INDEX_TYPESCRIPT" , TypeScriptMode .class , TypeScriptMode .FULL );
194205 this .defaultEncoding = getEnvVar ("LGTM_INDEX_DEFAULT_ENCODING" );
195206 setupFileTypes ();
207+ setupXmlMode ();
196208 setupMatchers ();
197209 }
198210
@@ -272,14 +284,30 @@ private void setupFileTypes() {
272284 String extension = fields [0 ].trim ();
273285 String fileType = fields [1 ].trim ();
274286 try {
275- fileTypes .put (extension , FileType .valueOf (StringUtil .uc (fileType )));
287+ fileType = StringUtil .uc (fileType );
288+ if ("XML" .equals (fileType )) {
289+ if (extension .length () < 2 )
290+ throw new UserError ("Invalid extension '" + extension + "'." );
291+ xmlExtensions .add (extension .substring (1 ));
292+ } else {
293+ fileTypes .put (extension , FileType .valueOf (fileType ));
294+ }
276295 } catch (IllegalArgumentException e ) {
277296 Exceptions .ignore (e , "We construct a better error message." );
278297 throw new UserError ("Invalid file type '" + fileType + "'." );
279298 }
280299 }
281300 }
282301
302+ private void setupXmlMode () {
303+ String xmlMode = getEnvVar ("LGTM_INDEX_XML_MODE" , "DISABLED" );
304+ xmlMode = StringUtil .uc (xmlMode .trim ());
305+ if ("ALL" .equals (xmlMode ))
306+ xmlExtensions .add ("xml" );
307+ else if (!"DISABLED" .equals (xmlMode ))
308+ throw new UserError ("Invalid XML mode '" + xmlMode + "' (should be either ALL or DISABLED)." );
309+ }
310+
283311 /** Set up include and exclude matchers based on environment variables. */
284312 private void setupMatchers () {
285313 setupIncludesAndExcludes ();
@@ -402,6 +430,7 @@ public void run() throws IOException {
402430 try {
403431 extractSource ();
404432 extractExterns ();
433+ extractXml ();
405434 } finally {
406435 shutdownThreadPool ();
407436 }
@@ -733,10 +762,33 @@ private void logEndProcess(long timedLogMessageStart, String message) {
733762 System .out .flush ();
734763 }
735764
765+ public Set <String > getXmlExtensions () {
766+ return xmlExtensions ;
767+ }
768+
769+ protected void extractXml () throws IOException {
770+ if (xmlExtensions .isEmpty ())
771+ return ;
772+ List <String > cmd = new ArrayList <>();
773+ cmd .add ("odasa" );
774+ cmd .add ("index" );
775+ cmd .add ("--xml" );
776+ cmd .add ("--extensions" );
777+ cmd .addAll (xmlExtensions );
778+ ProcessBuilder pb = new ProcessBuilder (cmd );
779+ try {
780+ pb .redirectError (Redirect .INHERIT );
781+ pb .redirectOutput (Redirect .INHERIT );
782+ pb .start ().waitFor ();
783+ } catch (InterruptedException e ) {
784+ throw new CatastrophicError (e );
785+ }
786+ }
787+
736788 public static void main (String [] args ) {
737789 try {
738790 new AutoBuild ().run ();
739- } catch (IOException | UserError e ) {
791+ } catch (IOException | UserError | CatastrophicError e ) {
740792 System .err .println (e .toString ());
741793 System .exit (1 );
742794 }
0 commit comments