Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix #8: Typedef and anonymous structs.
  • Loading branch information
ciechowoj committed Sep 8, 2016
1 parent c09e675 commit cb7627c
Show file tree
Hide file tree
Showing 19 changed files with 694 additions and 147 deletions.
2 changes: 1 addition & 1 deletion clang/Cursor.d
Expand Up @@ -242,7 +242,7 @@ struct Cursor
return clang_getCursorLanguage(cx);
}

equals_t opEquals (const ref Cursor cursor) const
equals_t opEquals (in Cursor cursor) const
{
return clang_equalCursors(cast(CXCursor) cursor.cx, cast(CXCursor) cx) != 0;
}
Expand Down
39 changes: 28 additions & 11 deletions clang/SourceLocation.d
Expand Up @@ -31,7 +31,12 @@ struct SourceLocation
{
Spelling spell;

clang_getSpellingLocation(cx, &spell.file.cx, &spell.line, &spell.column, &spell.offset);
clang_getSpellingLocation(
cx,
&spell.file.cx,
&spell.line,
&spell.column,
&spell.offset);

return spell;
}
Expand All @@ -40,7 +45,12 @@ struct SourceLocation
{
Spelling spell;

clang_getExpansionLocation(cx, &spell.file.cx, &spell.line, &spell.column, &spell.offset);
clang_getExpansionLocation(
cx,
&spell.file.cx,
&spell.line,
&spell.column,
&spell.offset);

return spell;
}
Expand Down Expand Up @@ -86,18 +96,25 @@ struct SourceLocation
@property string toString() const
{
import std.format : format;
auto s = spelling;
return format("SourceLocation(file = %s, line = %d, column = %d, offset = %d)", s.file, s.line, s.column, s.offset);
auto localSpelling = spelling;

return format(
"SourceLocation(file = %s, line = %d, column = %d, offset = %d)",
localSpelling.file,
localSpelling.line,
localSpelling.column,
localSpelling.offset);
}

bool lexicalLess(in SourceLocation that)
@property string toColonSeparatedString() const
{
File fileA, fileB;
uint offsetA, offsetB;

clang_getSpellingLocation(cx, &fileA.cx, null, null, &offsetA);
clang_getSpellingLocation(that.cx, &fileB.cx, null, null, &offsetB);
import std.format : format;
auto localSpelling = spelling;

return fileA != fileB ? fileA < fileB : offsetA < offsetB;
return format(
"%s:%d:%d",
localSpelling.file.name,
localSpelling.line,
localSpelling.column);
}
}
32 changes: 32 additions & 0 deletions clang/TranslationUnit.d
Expand Up @@ -260,6 +260,38 @@ struct TranslationUnit
return relativeLocationAccessorImpl(cursor.all);
}

bool delegate (SourceLocation, SourceLocation)
relativeLocationLessOp()
{
auto accessor = relativeLocationAccessor();

bool lessOp(SourceLocation a, SourceLocation b)
{
if (a.file == b.file)
return a.offset < b.offset;
else
return accessor(a) < accessor(b);
}

return &lessOp;
}

bool delegate (Cursor, Cursor)
relativeCursorLocationLessOp()
{
auto accessor = relativeLocationAccessor();

bool lessOp(Cursor a, Cursor b)
{
if (a.file == b.file)
return a.location.offset < b.location.offset;
else
return accessor(a.location) < accessor(b.location);
}

return &lessOp;
}

private struct TokenRange
{
CXTranslationUnit cx;
Expand Down
53 changes: 43 additions & 10 deletions dstep/Configuration.d
Expand Up @@ -77,6 +77,14 @@ struct Configuration
/// do not translate following symbols
@("skip", "Skip translation of <symbol>.")
string[] skipSymbols;

/// print diagnostic informations
@("print-diagnostics", "Print diagnostic informations [default].")
bool printDiagnostics = true;

/// action to take on symbol collision
@("collision-action", "Action to take when translated symbol collides with a preexisting symbol [default].")
CollisionAction collisionAction = CollisionAction.rename;
}

template makeGetOptArgs(alias config)
Expand All @@ -85,9 +93,11 @@ template makeGetOptArgs(alias config)

template expand(alias spelling)
{
alias member = Alias!(__traits(getMember, config, spelling));

static if (
__traits(compiles, &__traits(getMember, config, spelling)) &&
__traits(getAttributes, __traits(getMember, config, spelling)).length == 2)
__traits(getAttributes, member).length == 2)
{
auto ptr() @property
{
Expand All @@ -96,28 +106,51 @@ template makeGetOptArgs(alias config)

auto formatHelp(alias spelling)(string help)
{
import std.algorithm : canFind;
import std.format : format;
import std.string : replace;

import std.algorithm;
import std.format;
import std.string;
import std.range;

Configuration config;

static if (is(typeof(__traits(getMember, config, spelling)) == bool))
string suffix;

static if (is(typeof(member) == bool) || is(typeof(member) == enum))
{
auto default_ = "[default]";

if (help.canFind(default_))
return help.replace(
{
help = help.replace(
default_,
format("[default: %s]", __traits(getMember, config, spelling)));
else
return help;

static if (is(typeof(member) == bool))
{
suffix = "=true|false";
}
else
{
suffix = format(
"=%s",
join([ __traits(allMembers, typeof(member)) ], "|"));
}
}
}
else
{
return help;
auto beginning = findSplitBefore(help, "<");

if (!beginning[0].empty)
{
auto placeholder = findSplitAfter(beginning[1], ">");

if (!placeholder[0].empty)
suffix = format(" %s", placeholder[0]);
}
}

return format("%s!%s", suffix, help);
}

alias expand = AliasSeq!(
Expand Down
3 changes: 2 additions & 1 deletion dstep/driver/Application.d
Expand Up @@ -183,11 +183,12 @@ private struct ParseFile
options.spaceAfterFunctionName = config.spaceAfterFunctionName;
options.skipDefinitions = setFromList(config.skipDefinitions);
options.skipSymbols = setFromList(config.skipSymbols);
options.printDiagnostics = config.printDiagnostics;
options.collisionAction = config.collisionAction;

auto translator = new Translator(translationUnit, options);
translator.translate;
}

}

~this ()
Expand Down
21 changes: 10 additions & 11 deletions dstep/main.d
Expand Up @@ -175,7 +175,7 @@ int main (string[] args)
}
catch (Throwable e)
{
writeln("An unknown error occurred: ", e);
writeln("dstep: an unknown error occurred: ", e);
throw e;
}

Expand Down Expand Up @@ -206,16 +206,16 @@ void showHelp (Configuration config, GetoptResult getoptResult)
else
this.option = option.optLong;

this.help = option.help;
auto pair = findSplitAfter(option.help, "!");

auto beginning = findSplitBefore(this.help, "<");

if (!beginning[0].empty)
if (!pair[0].empty)
{
auto placeholder = findSplitAfter(beginning[1], ">");

if (!placeholder[0].empty)
this.option ~= format(" %s", placeholder[0]);
this.option ~= pair[0][0 .. $ - 1];
this.help = pair[1];
}
else
{
this.help = option.help;
}
}

Expand Down Expand Up @@ -246,8 +246,7 @@ void showHelp (Configuration config, GetoptResult getoptResult)
helpString.put(format(" %-*s %s\n", cast(int) maxLength + 1, entry.option, entry.help));

helpString.put(
"\nTo disable boolean options use false, e.g. --comments=false.\n"
"All options that Clang accepts can be used as well.\n"
"\nAll options that Clang accepts can be used as well.\n"
"Use the `-h' flag for help.");

writeln(helpString.data);
Expand Down
103 changes: 97 additions & 6 deletions dstep/translator/Context.d
Expand Up @@ -32,6 +32,7 @@ class Context
private Translator translator_ = null;
private Output globalScope_ = null;
private Cursor[string] typeNames_;
private string[Cursor] translatedSpellings;
public MacroDefinition[string] macroDefinitions;

Options options;
Expand Down Expand Up @@ -136,16 +137,106 @@ class Context
return typedefIndex_.typedefParent(cursor);
}

private string translateSpellingImpl(in Cursor cursor)
{
return cursor.spelling == ""
? generateAnonymousName(cursor)
: cursor.spelling;
}

public string translateSpelling(in Cursor cursor)
{
auto typedefp = typedefParent(cursor.canonical);
if (auto spelling = (cursor in translatedSpellings))
{
return *spelling;
}
else
{
auto spelling = translateSpellingImpl(cursor);
translatedSpellings[cursor] = spelling;
return spelling;
}
}

if (typedefp.isValid && cursor.spelling == "")
return typedefp.spelling;
private void printCollisionWarning(
string spelling,
Cursor cursor,
Cursor collision)
{
import std.format : format;
import std.stdio : writeln;

if (options.printDiagnostics)
{
auto message = format(
"%s: warning: a type renamed to '%s' due to the " ~
"collision with the symbol declared in %s",
cursor.location.toColonSeparatedString,
spelling,
collision.location.toColonSeparatedString);

writeln(message);
}
}

private void throwCollisionError(
string spelling,
Cursor cursor,
Cursor collision) {
import std.format : format;

throw new TranslationException(
format(
"%s: error: a type name '%s' " ~
"collides with the symbol declared in %s",
cursor.location.toColonSeparatedString,
spelling,
collision.location.toColonSeparatedString));
}

public string translateTagSpelling(Cursor cursor)
{
if (auto spelling = (cursor.canonical in translatedSpellings))
{
return *spelling;
}
else
return cursor.spelling == ""
? generateAnonymousName(cursor)
: cursor.spelling;
{
auto typedefp = typedefParent(cursor.canonical);
string spelling;

if (typedefp.isValid && cursor.spelling == "")
{
spelling = typedefp.spelling;
}
else
{
string tentative = translateSpellingImpl(cursor);

spelling = tentative;

if (options.collisionAction != CollisionAction.ignore)
{
auto collision = spelling in macroIndex.globalCursors;

while (collision &&
collision.canonical != cursor.canonical &&
collision.canonical != typedefParent(cursor.canonical))
{
if (options.collisionAction == CollisionAction.abort)
throwCollisionError(spelling, cursor, *collision);

spelling ~= "_";
printCollisionWarning(spelling, cursor, *collision);
collision = spelling in macroIndex.globalCursors;
}
}
}

translatedSpellings[cursor.canonical] = spelling;

return spelling;
}
}

public Translator translator()
Expand Down
2 changes: 1 addition & 1 deletion dstep/translator/Enum.d
Expand Up @@ -60,7 +60,7 @@ void translateEnumDef(Output output, Context context, Cursor cursor)
auto spelling = "enum";

if (!anonymous || variables || !cursor.isGlobal)
spelling = "enum " ~ translateIdentifier(context.translateSpelling(cursor));
spelling = "enum " ~ translateIdentifier(context.translateTagSpelling(cursor));

output.subscopeStrong(cursor.extent, "%s", spelling) in
{
Expand Down

0 comments on commit cb7627c

Please sign in to comment.