Skip to content

Commit

Permalink
Add some support for parsing attributes defined by macros (xoofx#51)
Browse files Browse the repository at this point in the history
Only basic parsing is performed by this PR but it does allow for
a macro to hold an scoped attribute with arguments.
  • Loading branch information
stevew-cgnx committed Apr 22, 2022
1 parent 2f873c4 commit c51f014
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
24 changes: 24 additions & 0 deletions src/CppAst.Tests/TestAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,30 @@ struct [[deprecated(""old"")]] TestMessage{
);
}

[Test]
public void TestCpp11StructAttributesWithMacro()
{
ParseAssert(@"
#define CLASS_ATTRIBUTE [[deprecated]]
struct CLASS_ATTRIBUTE Test{
int a;
int b;
};", compilation =>
{
Assert.False(compilation.HasErrors);

Assert.AreEqual(1, compilation.Classes.Count);
Assert.AreEqual(1, compilation.Classes[0].Attributes.Count);
{
var attr = compilation.Classes[0].Attributes[0];
Assert.AreEqual("deprecated", attr.Name);
}
},
// we are using a C++14 attribute because it can be used everywhere
new CppParserOptions() { AdditionalArguments = { "-std=c++14" }, ParseAttributes = true }
);
}

[Test]
public void TestCpp11VariablesAttributes()
{
Expand Down
63 changes: 62 additions & 1 deletion src/CppAst/CppModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,41 @@ private List<CppAttribute> ParseFunctionAttributes(CXCursor cursor, string funct
return attributes;
}

private (string, string) GetNameSpaceAndAttribute(string fullAttribute)
{
string[] colons = { "::" };
string[] tokens = fullAttribute.Split(colons, System.StringSplitOptions.None);
if (tokens.Length == 2)
{
return (tokens[0], tokens[1]);
}
else
{
return (null, tokens[0]);
}
}


private (string, string) GetNameAndArguments(string name)
{
if (name.Contains("("))
{
Char[] seperator = { '(' };
var argumentTokens = name.Split(seperator, 2);
var length = argumentTokens[1].LastIndexOf(')');
string argument = null;
if (length > 0)
{
argument = argumentTokens[1].Substring(0, length);
}
return (argumentTokens[0], argument);
}
else
{
return (name, null);
}
}

private bool ParseAttributes(TokenIterator tokenIt, ref List<CppAttribute> attributes)
{
// Parse C++ attributes
Expand Down Expand Up @@ -1414,6 +1449,32 @@ private bool ParseAttributes(TokenIterator tokenIt, ref List<CppAttribute> attri
return tokenIt.Skip(")"); ;
}

// See if we have a macro
var value = tokenIt.PeekText();
var globalContainer = (CppGlobalDeclarationContainer)_rootContainerContext.DeclarationContainer;
var macro = globalContainer.Macros.Find(v => v.Name == value);
if (macro != null)
{
if (macro.Value.StartsWith("[[") && macro.Value.EndsWith("]]"))
{
CppAttribute attribute = null;
var fullAttribute = macro.Value.Substring(2, macro.Value.Length - 4);
var (scope, name) = GetNameSpaceAndAttribute(fullAttribute);
var (attributeName, arguments) = GetNameAndArguments(name);

attribute = new CppAttribute(attributeName);
attribute.Scope = scope;
attribute.Arguments = arguments;

if (attributes == null)
{
attributes = new List<CppAttribute>();
}
attributes.Add(attribute);
tokenIt.Next();
return true;
}
}
return false;
}

Expand Down Expand Up @@ -2367,4 +2428,4 @@ public CppContainerContext(ICppContainer container)
public bool IsChildrenVisited;
}
}
}
}

0 comments on commit c51f014

Please sign in to comment.