Antlr4 C# targets and output path of generated files - c#

I have a C# solution with an Antlr3 grammar file, and I'm trying to upgrade to Anltr4. It turns out the grammar was the easy part (it became better, and one third the size!). Generating the parser turned out to be the tricky part.
In the old solution I merely ran AntlrWorks to update the lexer and parser .cs files when the grammar file changed. The lexer and parser were included directly in the same project as the grammar so the framework around the parser could make use of them directly.
With the Antlr4 targets for C# I noticed that (at least by default) the output path of the generated Parser C# classes is in the intermediate directory, e.g. obj\Debug. This means I can't use the parser directly in the same project. Am I supposed to change the output path if I want the generated source usable in my sln? Don't I want it in my sln?
I tried making a separate project for the parser generation, that is, a project containing only the grammar file. When this project is built using the Antlr4 targets, the resulting assembly can be referenced from projects needing the parser classes. However, if this project is included in the solution I still don't get any intellisense in visual studio since it bases its intellisense on source files for loaded projects, so it is still not quite usable. The only way I could get it working properly was to build then unload the parser project, and have other projects reference it as an assembly file rather than a project.
EDIT:
After looking on the antlr-interest list I found this thread indicating that the problem with intellisense may be Resharpers fault. If this is the case, then my question is rather how to keep using both Antlr4 and Resharper in my solution?
https://groups.google.com/forum/#!topic/antlr-discussion/QSuJXphaBDg

I found an extension for Resharper: ReSharper.ExternalCode.
Tip for Antlr: add obj\Debug in Resharper -> Code Inspection -> External Code and reload solution.
It's works for me.

There is an easy way to get the best of both Antlr 4 and Visual Studio. You are on the right track in having a separate grammar project and implementation project, but you are missing a couple steps.
Follow these steps to get the Intellisense working
In Visual Studio, go to Tools -> Extensions and Updates and search the Online section for "ANTLR Language Support" by Sam Harwell.
This does a few things:
Adds Templates for the combined grammars.
Adds Syntax Highlighting
Adds an MSBuild target for the grammar to generate the parser.
In your solution, set up your project structure like this:
Solution
Grammar Project
ANTLR 4 Combined Grammar
Implementation Project
Folder for Links to Generated files
Listener Implementation Class
Write and Compile your grammar.
In your folder for the Links to Generated Files, Right-Click the folder and click Add -> Existing Item
Browse to Grammar Project\obj\Debug and select all the generated parser files.
This next step is important. On the Add button there is a little drop-down arrow. Click the drop-down arrow and click "Add As Link".
This will add the generated files to the implementation project using a symbolic link instead of a direct copy.
This gives the added benefit of not having to remove and re-add the parser files if you have to change your grammar later.
Intellisense should work now for your generated parser classes, and you don't
even have to disable ReSharper.

You are encountering a known bug with ReSharper. The ANTLR 3 and ANTLR 4 C# build integration is reliable, and uses long-established patterns that Microsoft uses with other languages and code generation tasks. Your options are:
Stop using ReSharper
Get the ReSharper authors to address the lack of support for this feature, or
Modify the ANTLR 4 target to work around the limitation in ReSharper, which will introduce other problems into the build which may or may not be acceptable for your use.
Option 1 is certainly the least expensive, and most likely to provide reliable long-term support for your projects.

Related

Simple approach to updating AssemblyInformationalVersion via TeamCity's AssemblyInfo patcher feature

By default a Visual Studio C# Library/Console etc project comes with an AssemblyInfo.cs file that does not include AssemblyInformationalVersionAttribute. TeamCity allows patching this attribute if found in AssemblyInfo.cs using AssemblyInfoPatcher.
Problem
A zero effort way of including AssemblyInformationalVersion for TeamCity.
Possible Solutions
Use a GlobalAssemblyInfo.cs file and link to each project, downside: each new project will have to be linked, frustratingly annoying if (often) forget to create link
Add AssemblyInformationalVersionAttribute to all templates in Common7\IDE\ProjectTemplates\CSharp\, downside: do it on each devs machine, mainly overkill
A first build step that runs a script based on this SO answer and creates links on all .cspprojs, downside: will have to check back in for patching step, overly complicated
Reason
The AssemblyInformationalVersion is useful because you can put any text there - I like to put the git hash of the commit used to build the assembly in it
Have you a better idea?

How is dirs.proj used?

I'm afraid I may be asking a really dumb question, but I can't seem to find anything that makes this clear. I usually work on smaller applications but am now working on a larger one with several assemblies in a baseline framework and several assemblies for a product line domain (with more to come). I would like to manage the build by configuring MSBuild. I've done a lot of online research (specifically with several MSDN articles I found) and now feel knowledgeable enough to be dangerous.
I understand that in csharp the *.csproj file can be unloaded and modified with properties, items, and targets to control the build process. I also understand that I can import my own targets file to help separate and organize. In this link though (https://msdn.microsoft.com/en-us/magazine/dd483291.aspx) a multilevel project build is organized with node-level dirs.proj files. This is confusing to me and has raised several questions I can't seem to find an answer to:
What is the difference in a *.proj and *.csproj file?
Can a *.proj be setup in VS to load on Build with F6 or does using this require use of the command prompt only? (i.e. "msbuild dirs.proj /t:Build").
Does dirs.proj load automatically? If so, my study-by is not working correctly, yet it does with command prompt.
Or am I overlooking something all the way around with "dirs.proj" Maybe it's just a substitue name for one of the project *.csproj files? If that was the case though there wouldn't have been a need for the root node's dirs.proj which from what I can tell doesn't have an actual project associated to it.
Anyways, I've seen dirs.proj mentioned in several forums regarding issues, but no where can I find how it's loaded or used in VS (outside of manual command prompt building which seems unreasonable if this is used to organize the build but the build won't really take a huge amount of time). I'm hoping someone can help me achieve that a-ha moment with this.
Thanks in advance.
Dirs.proj is an MSBuild convention typically used when dealing with very large source trees (> than 20 projects). I've worked with Microsoft engineers at a previous company and the dirs.proj convention appears to be one that Microsoft developed and uses internally to manage very large source trees.
A very good implementation reference for this is the Python Tools for Visual Studio project on CodePlex GitHub.
The link you shared by Sayed Ibrahim Sashimi is a very good explanation of the reasoning behind the msbuild paradigm, but it doesn't do a very good job of showing a practical example of how it works. The Python Tools project is an outstanding reference for this.
The idea behind using this paradigm is simple. I'd wager a guess that most .NET software engineers work on somewhat limited-scale projects that don't deal with more than 5-10 projects at a time, and they manage these projects in Visual Studio via Solution (.sln) files. They may even instruct their build system to run builds on the .sln. This works fine until you start thinking about scaling your product into or combining it with something larger, such as a platform with many, many projects. Solution files are not MSBuild files and as such they are not extensible like MSBuild is and they suffer massive performance penalties when dealing with large numbers of projects.
From an MSBuild perspective, dirs.proj stands in for Visual Studio .sln files. The difference, however, is that dirs.proj don't just include .csproj (and the like) as .sln do, rather, they can include source subtrees (e.g. other nested dirs.proj). So, building the root dirs.proj can result in the entire source tree being built, or building a nested dirs.proj will result in that subtree being built.
Therefore, the paradigm encourages you to look at your source as a series of interdependent nodes organized into features or product areas. That way, engineers can work on different source subtrees in very large projects without having to deal with the entire source tree, as you would have to with a VS solution.
Using this paradigm also carries certain benefits that don't come with .sln files. For example, if one project references a project from another, separate subtree, msbuild will build that reference first, automatically. Additionally, your source nodes can carry their own build settings, allowing them to be built dynamically using different build settings based on build scenario. For example, under one scenario a SharePoint source subtree needs WSP packaging, a C# subtree needs to be built without .pdb, a DB subtree needs to generate dacpacs, and the entire source tree needs to sign their assemblies using myCorp.snk and set build output to the $(buildRoot)\Output directory.
dirs.proj aren't opened via visual studio - they're built on the command line using msbuild. The only pain point is that the files have to be hand-curated.
So, long answer short take a look at the Python Tools project and see how they're using dirs.proj. Note how the entire source tree has common settings managed by Common.Build.settings, and how msbuild properties in this .settings file are used in the various .csproj files.

A way to modify class (and general assembly) data at build time

This thing I want to do might not even be worth doing but I thought it would be cool.
So what I want to do is to have some code that runs when my project is building (not only when compiling), and adds stuff to my classes based on things like attributes and general code analysis. What I want to do is have dynamically generated fields/properties that are usable through intellisense, but not visible in the actual source.
The reason for that being that I might potentially want to generate a lot of them, and outputting them to source would turn into a mess very quickly.
The potential possibilities of a system like that would be stuff like vector swizzling.
Is there maybe a library of some sort for that that I could just plug my generation code in? If not, what would be the best way to approach this, if there is any?
The most visible example of this is done by Microsoft for XAML files. During the build, a C# source file is created for each XAML file and placed in the obj/Debug or obj/Release folder. In addition to that, the MSBuild .targets file where the relevant tasks are defined is specially configured to tell Visual Studio that the generated files are required for proper IntelliSense support, which means you don't actually have to explicitly build the project in order for IntelliSense to allow items declared in XAML to be used in C# code elsewhere in the project.
This is exactly the method I use for generating code for ANTLR grammar files during a build. You can see a complete example with a build task assembly and custom .targets file here:
https://github.com/antlr/antlrcs/tree/master/AntlrBuildTask
You should be aware that some 3rd party extensions for Visual Studio completely replace the IntelliSense support with their own implementation of code completion. Some of these extensions are known to not support the MSBuild IntelliSense extensibility features required for this to work with custom code generators. If you run into problems with IntelliSense and have any extensions installed, you may find that removing the extensions completely resolves the problems.
You should compile code by the class CSharpCodeProvider/ICodeCompiler/CompilerParameters when application run.

Syntax highlighting for non-project files in Visual Studio

I have a simple C# project which loads external C# files at startup to be used as scripts. Unfortunately when editing any of these 'non-project' files in Visual Studio I only get the most basic of syntax highlighting, since classes and types within the project are not known in the context of this external file.
Without adding the files to my project (defeating the purpose of them being external scripts), is there any way I can define an external interface or somehow otherwise convince Visual Studio (2008) to parse the code within these files in the context of the classes in the project?
A couple of clarifications (with thanks to the early answerers)
People should be able to edit these scripts without access to my source code
People shouldn't have to set up an entire Visual Studio project to edit one source file that's likely to contain less that 10 lines of actual code.
You will always need a reference to these classes. Maybe you can add these files as a link to the project or to a new project with a reference.
Visualstudio needs some informations to accomplish that.
I would think about the Bridge Pattern and you need to add the class body in the same file
http://en.wikipedia.org/wiki/Bridge_pattern
or using mock objects- you can easily use them to provide syntax highlighting without sharing your code (the same here - all in one file):
http://en.wikipedia.org/wiki/Mock_object
You can separate the script and the assiting classes if you would allow having a project file.

Compare compiled .NET assemblies?

Are there any good programs out there to compare to compile .NET assemblies?
For example I have HelloWorld.dll (1.0.0.0) and HelloWorld.dll (2.0.0.0), and I want to compare differences how can I do this?
I know I can use .NET Reflector and use the Assembly Diff plugin. Are there any other good tools out there to do this?
Ways to Compare .NET Assemblies suggests
Commercial:
NDepend
Free:
JustAssembly (only shows differences in API)
BitDiffer (same)
Reflector Diff Add-in (which you've already discovered, but not available anymore)
Existing compare tools like Beyond Compare (commercial) can do this by special configuration. Here's how to do this for Beyond Compare:
Go to Tools → Options
Click New.., select "Text format", click OK
Give it a name (say, EXE, or DLL), and specify the mask as *.exe or *.dll
Click on tab Conversion and select "External program (Unicode filenames)"
Under "Loading", specify the path to ildasm and add %s /OUT:%t /NOBAR (i.e.: C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe %s /OUT:%t /NOBAR)
Make sure to check disable editing.
Click Save, then Close
Restart BC and open two exe files to compare, it should decompile into ilasm automatically now.
You can also add syntax highlighting to this new format. I plan to send the syntax file to them so that it'll become available to share.
Two ways.
You could ILDASM and diff with classic tools.
Or you could use NDepends, which will cost for that feature.
[Piece to C# bloaters..]
I just had to compare two revisions of the same DLL, which had the same version (I needed to implement a small hotfix, and deploy the DLL in production, but I wanted to make sure that no other changes leaked into code). Ideally, I would want the Assemby Diff add-in to show me the difference, but it does not work (it thinks that I'm comparing a DLL to itself). So this is what I did:
Created two folders to hold disassembled source files.
Used the Reflector's Export option (from context menu) to generate source files from each DLL in the folders created in previous step.
Used the free DiffMerge tool to compare two directories; the tools showed me the modified files and the difference.
It's a bit kludgy, but seems to work. I wish the Assembly Diff add-in worked, though.
UPDATE: The latest version of the Assembly Diff add-in is supposed to fix the issue of comparing two versions of the same assembly. Give it a try.
The tool NDepend offers many features to compare compiled .NET assemblies.
First from the NDepend Start Page click: Compare 2 versions of a code base. This will let you provide older and newer versions of your assemblies.
Then after NDepend has analyzed both older and newer assemblies, you can use the panel Search by Change. It is dedicated to browse assemblies code diff. Notice that:
If source code is available, just right click an element and click Diff Source. In the NDepend options you can plug to NDepend any code diff tool (Visual Studio, Beyond Compare...)
If you don't have the source code and just only the raw assemblies, there is the option Compare older and newer version disassembled with ILSpy. ILSpy v7.0 and upper versions are supported. This menu works on assembly, namespace, type and method level and you can choose to decompile to C# or IL.
Notice also in the screenshot that a CQLinq code query is generated to browse the diff.
from m in Application.Methods
where m.CodeWasChanged()
select new { m, m.NbLinesOfCode }
Many others default diff queries and rules are proposed by default, that will let you browse .NET code diff in a smart way.
Types that used to be 100% covered but not anymore
API Breaking Changes: Methods
Avoid making complex methods even more complex
Avoid decreasing code coverage by tests of types
From now, all types added or refactored should respect basic quality principles
Avoid transforming an immutable type into a mutable one
Heuristic to find types moved from one namespace or assembly to another
Disclaimer: I am one of the developer of the tool.
One more option is LibCheck from Microsoft.
Pretty old console tool for just getting public API diff. I could not run without debugging and retargeting to a more recent .net version. However, it gave me very clear output and I am going to use it later.
Here is an article with screenshots.
Here's a thinking outside the box approach whcih works fine.
Dump your old and new assemblies with dnSpy, dotPeek or JustDecompile into projects.
Create a new Git repo and commit the old assembly code first.
In your local repo folder delete all the files/folders except for ".git" and paste the new assembly files.
Either commit the new changes and view changes on say Github or use a Git viewer like Fork. Easy code comparison for free.
Java has a nice one: Semantic Diff Utilities

Categories

Resources