Welcome to the CodeSmith Community!

Using CodeSmith.CodeFileParser

CodeSmith Community

A description has not yet been added to this group.

Using CodeSmith.CodeFileParser

Rate This
  • Comments 15

The CodeFileParser

In CodeSmith v5.1 we are introducing a new feature: the CodeFileParser!

The Inspiration
We are always wondering, how can we make CodeSmith better? We noticed that more and more cars have the 'flex fuel' logo on them these days; so we asked ourselves, "How can we learn from that? How can we make CodeSmith's fuel more flexible?"
Well, CodeSmith is fueled by metadata, so how can we make metadata more flexible? ...and then it came to us: add more metadata!

The Feature
The CodeFileParser will make it easier for CodeSmith templates to use code files as their metadata source. It is a simple class that takes in a file path, or even a content string, parses the class, and returns an easy to walk/search DOM object.
So think about that for a moment; this means that you can generate code, *dramatic pause*, from code.

I'll just let that sink in...
...take your time...
...pretty sweet, huh?

The Implementation

The Class
CodeSmith.Engine now contains the CodeFileParser class. It is capable of parsing both C# and VB code.
As mentioned above, it is capable of taking in a file path or a content string, and it will take care of reading the file (or string) and parsing the contents for you.
Under the hood the CodeFileParser uses the public NRefactory libraries created by the great team over at SharpDevelop.

// There are overloads that don't require basePath or parseMethodBodies.
public CodeFileParser(string fileName, string basePath, bool parseMethodBodies)
// There are overloads that don't require parseMethodBodies.
public CodeFileParser(string source, SupportedLanguage language, bool parseMethodBodies)

The Selection Methods
Most of the methods in NRefactory return position information in the form of Location objects, which, while very descriptive, are not the easiest thing to use when trying to take substrings or selections from the existing code.
Because this can be very important when using the object DOM to assist with code generation, we have added several methods to assist with getting substrings and selections; these methods take in Location objects and return strings.

public string GetSectionFromStart(Location end)
public string GetSectionToEnd(Location start)
public string GetSection(Location start, Location end)

The CodeDomCompilationUnit
To quick and easily walk the DOM, the CodeFileParser exposes a (lazy loaded) property that returns System.CodeDom.CodeCompileUnit object.
This is a standard .NET object that contains a complete code graph; this object is the quickest and easiest way to traverse your metadata.
For more information about the CodeCompileUnit, please check out MSDN article.

The Visitor
When more advanced or customized information is required, the CodeFileParser exposes the CompilationUnit object, which is capable of taking in a visitor object to traverse the DOM and bring back specific data.
This is an NRefactory feature, and it only requires that your visitor object implement the AbstractAstVisitor class.

The Example

The We're Already Using It!
We are already using the CodeFileParser in CodeSmith and our Plinqo templates!
In CodeSmith we have implemented the CodeFileParser in our InsertClassMergeStrategy; it allows us to parse the existing code file and determine where we need to insert our new content.
In Plinqo we use the CodeFileParser to assist with our MetaData class merge; it allows us to make a map of all the properties in that class and then preserve their attributes during regeneration.

The Template Code

<%@ CodeTemplate Language="C#" TargetLanguage="Text" Debug="False" CompilerVersion="v3.5" %>
<%@ Property Category="2.Class" Name="TheFile" Type="CodeFileParser" Optional="False" %>
<%@ Assembly Name="CodeSmith.CodeParser" %>
<%@ Import Namespace="System.CodeDom" %>

<%  foreach(CodeNamespace n in TheFile.CodeDomCompilationUnit.Namespaces) { %>
Namespace: <%= n.Name %>
<%      foreach(CodeTypeDeclaration t in n.Types) { %>
    Type: <%= t.Name %>
<%          foreach(CodeTypeMember m in t.Members) { %>
        Member: <%= m.Name %>
<%          } %>
<%      } %>
<%  } %>

Small footnote, thanks to Seinfeld for inspiring my section title names in this blog post.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • * Please enter your name
  • * Please enter a comment
  • Post
  • Personal Licenses Available Now CodeSmith is now offering personal licenses for individual developers

  • Oh, YES!

    I've built some of my own templates using Reflection but this... if this thing works half as good as it seems then this is going to make my life much, much easier.

  • Any way to use this with ActiveSnippets ?

  • Hello,

    Yes, you should be able to use this with active snippets but you will need to pass in the name of the file you are working with.

    Thanks

    -Blake Niemyjski

  • Hi Blake,

    Thanks for taking time to reply.

    I've been trying this, but unfortunately I keep getting an InvalidOperationException with message "Empty Type".

    Do the code files need to have a specific format ? Also, where is the documentation of this feature ? I haven't found it in either the CodeSmith docs or the API docs.

    regards

  • Hello,

    This is the only documentation we currently have on this feature:\ . If you could send support your active snippet with the steps to reproduce, I'll take a look.

    Thanks

    -Blake Niemyjski

  • Blake,

    Though I appreciate the good work of the CodeSmith team, I have to say that I'm quite disapointed at the lack of proper documentation in many area of the product.

    For example, the CodeFileParser class was introduced in CodeSmith 5.1, and this blog post already dates back more than a year, and still no documentation !!

    As for the snippet, I'll send you both the template and C# source file causing the problem.

  • Hello,

    If you can put together a list of areas that you think need to be updated. I'll add it to the task list on things to update in the near future.

    Thanks

    -Blake Niemyjski

  • Blake,

    Unfortunately, I can't possibly know which area of the documentation is lacking if I don't know that functionality X is implemented in the API. For example, how would I know about the CodeFileParser if Tom had not blogged about it ? It appears nowehere in the docs !!

    You're basically asking your customers to tell you (the developpers of the product) what should go in the documentation. Well, if it exists in the API or the product, then it MUST be documented. Period.

    I think you guys need to take a good unbiased look at the docs and try to see it through the eyes of a regular user. If you don't have the manpower to do it, then we could discuss my fees for this service.

    Regards

  • Blake,

    I forgot to ask you the e-mail to which I should send my files as stated in a previous post.

    Thanks

  • Hello,

    Please send them to: support@codesmithtools.com

    Thanks

    -Blake Niemyjski

  • I just updated to 5.3, and I can see that there is still no documentation on the CodeFileParser. Makes me wonder if it will ever come.

  • Hello,

    I've added this to the task list for updates to the documentation. It will make it into the documentation. If you have specific questions on how to use it, don't even hesitate to ask we would be more than happy to help.

    Thanks

    -Blake Niemyjski

  • Blake,

    Thank you for taking care of this.

    I don't have specific questions for now, but as always, having proper documentation is something that I value in commercial products for which I pay a yearly license fee.

    Regards

  • Docs have been added for this features here (docs.codesmithtools.com/.../Generating+from+Source+Code).

Page 1 of 1 (15 items)
Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • * Please enter your name
  • * Please enter a comment
  • Post