Skip to content

Commit

Permalink
Create support for auto converting includes to imports.
Browse files Browse the repository at this point in the history
Added command line options
--import-filter
A regular expression. All includes matching this will be converted to imports.
Only the basename part of the file name is used to generate the import.
--import-prefix
A prefix to give the imports. The import will have the form "<prefix><basename>"
  • Loading branch information
Mitten-O committed Nov 2, 2015
1 parent 5b4ad3a commit 1a3f8ee
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Alternatively compile libclang yourself:
## Limitations/Known issues

* Doesn't translate preprocessor macros of any kind
* Doesn't translate `#include` to `import`. A few standard C headers are translated
* Only very simplistic translation of `#include` to `import`. A few standard C headers are translated
* Doesn't translate C++ at all
* Umbrella headers. Some headers just serve to include other headers. If these other headers contain some form of protection, like `#error`, to be included directly this can cause problems for DStep
* Some headers are designed to always be included together with other header files. These headers may very well use symbols from other header files without including them itself. Since DStep is designed to convert header files one-by-one this doesn't work. There are two workarounds for this:
Expand Down
27 changes: 27 additions & 0 deletions dstep/driver/Application.d
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import clang.Util;

import dstep.core.Exceptions;
import dstep.translator.Translator;
import dstep.translator.IncludeHandler;

class Application : DStack.Application
{
Expand Down Expand Up @@ -70,6 +71,14 @@ class Application : DStack.Application
.on(&handleLanguage);

arguments("objective-c", "Treat source input file as Objective-C input.");

arguments('f',"import-filter", "A regex to filter includes that will be auto converted.")
.params(1)
.defaults(".*");

arguments('p',"import-prefix", "A prefix to add to any custom generated import")
.params(1)
.defaults("");
}

private:
Expand Down Expand Up @@ -123,6 +132,12 @@ private:
// FIXME: Cannot use type inference here, probably a bug. Results in segfault.
if (arguments.rawArgs.any!((string e) => e == "-ObjC"))
handleObjectiveC();

if (arguments["import-prefix"].hasValue)
handleAutoImportPrefix(arguments["import-prefix"].value);

if (arguments["import-filter"].hasValue)
handleAutoImportFilter(arguments["import-filter"].value);
}

void handleObjectiveC ()
Expand Down Expand Up @@ -160,6 +175,16 @@ private:
argsToRestore ~= language;
}

void handleAutoImportPrefix (string prefix)
{
includeHandler.setAutoImportPrefix(prefix);
}

void handleAutoImportFilter(string filter)
{
includeHandler.setAutoImportFilter(filter);
}

@property string[] remainingArgs ()
{
return arguments.rawArgs[1 .. $] ~ argsToRestore;
Expand Down Expand Up @@ -205,6 +230,8 @@ private:
println(" -ObjC, --objective-c Treat source input file as Objective-C input.");
println(" -x, --language <language> Treat subsequent input files as having type <language>.");
println(" -h, --help Show this message and exit.");
println(" -f, --import-filter A regex to filter includes that will be auto converted to imports.");
println(" -p, --import-prefix A prefix to add to any import generated from an include.");
println();
println("All options that Clang accepts can be used as well.");
println();
Expand Down
60 changes: 55 additions & 5 deletions dstep/translator/IncludeHandler.d
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
module dstep.translator.IncludeHandler;

import Path = std.path;
import std.regex;
import std.range;
import std.array;
import std.conv;

import mambo.core._;

Expand All @@ -26,6 +30,16 @@ class IncludeHandler
{
private string[] rawIncludes;
private string[] imports;

// True if includes should be converted to imports.
private bool convertIncludes = false;

// Includes matching this will be converted to imports.
private Regex!char convertableIncludePattern = regex(".*");

// Prefix for auto generated imports.
private string importPrefix = "";

static string[string] knownIncludes;

static this ()
Expand Down Expand Up @@ -109,21 +123,43 @@ class IncludeHandler
imports ~= "core.stdc.config";
}

/// Makes includes that match regex filter be converted to import with prefix.
void setAutoImportPrefix (string prefix)
{
this.convertIncludes = true;
this.importPrefix = prefix;
}

/// Makes includes that match regex filter be converted to import with prefix.
void setAutoImportFilter (string filter)
{
this.convertIncludes = true;
this.convertableIncludePattern = regex(filter);
}

string[] toImports ()
{
auto r = rawIncludes.map!((e) {
auto r = mambo.core.Array.map!((e) {
if (auto i = isKnownInclude(e))
return toImport(i);

else if( this.convertIncludes && isConvertableInclude(e) )
return toImport(autoConvertInclude(e));
else
return "";
});
})(rawIncludes);

auto imps = imports.map!(e => toImport(e));
auto imps = mambo.core.Array.map!(e => toImport(e))(imports);

return r.append(imps).filter!(e => e.any).unique.toArray;
}

/// Returns the base name (last component without extension) of a file path.
static string baseName (string path)
{
string last_component = text(retro(Path.pathSplitter(path)).front);
return Path.stripExtension( last_component );
}

private:

string toImport (string str)
Expand All @@ -140,4 +176,18 @@ private:

return null;
}
}

/// Checks if the given include file name should be converted to an import declaration.
bool isConvertableInclude (string include)
{
// Do not try to convert empty strings, no matter what the pattern says.
return include != "" && cast(bool)(matchFirst(include, convertableIncludePattern));
}


/// Generates an importable module name from an include file name.
string autoConvertInclude(string include)
{
return this.importPrefix ~ baseName(include);
}
}

0 comments on commit 1a3f8ee

Please sign in to comment.