Emacs 'csharp-mode' Byte Compilation Error - c#

When I attempt to byte compile csharp-mode under Emacs 24.2.1, I am getting the following error:
csharp-mode.el:2028:1:Error: Symbol's value as variable is void: csharp-enum-decl-re
This post confirms this same compilation problem and offers the following remedy:
I tried manually defining csharp-enum-decl-re by doing C-x C-e on the
defconst; this got it to compile.
This remedy worked for me as well! However, this remedy leaves me with a couple of questions:
Without pre-defining csharp-enum-decl-re, why does csharp-mode.el fail to byte-compile? (See the first link for the source code for csharp-mode.el.)
Without modifying csharp-mode.el, is there a better workaround for this compilation problem?
The error indicated at line 2028 concerns the following definition. Where is the dependency on csharp-enum-decl-re?
(defconst csharp-font-lock-keywords-2 (c-lang-const c-matchers-2 csharp)
"Fast normal highlighting for C# mode.")

To the best of my knowledge:
The file fails to byte-compile because a macro needs the value of a symbol that has not been defined. This error slips to some programmers because they are developing with an emacs session where they have eval'ed some of the code they are writing. A typical solution to the compilation error is to use eval-and-compile macro for those expressions needed to know at compile time.
Using eval-buffer before byte-compile is a workaround that saves you from modifying the source. Writing a patch and sending it to the author is another option.
Code is relatively tricky because of it relies heavily in macros. c-lang-defconst is suppose to define values for c-matchers-1, c-matchers-2 and c-matchers-3, but for c-matchers-2 the value of csharp-enum-decl-re is needed (see line 1304). Note that the name of the symbols (c-matchers-*) are created by the c-lang-defconst macro itself.

Related

Get error Diagnostics only for the delta of a CSharpCompilation

I'm using Roslyn to perform code manipulation on C# methods. To test the validity of the rewritten code, I examine compilation errors by calling Compilation.GetDiagnostics(). This is done only in test stages.
This works fine, but it is too slow, specially if the rewritten methods are part of a big project that apparently is compiled again each time.
I have the compilation delta since I use Compilation.UpdateCompilation(oldSyntaxTree, newSyntaxTree) but it is still too slow.
Is there a way to validate only the changed parts? Such as how Visual Studio determines syntax errors while we write code?
The rewritten code is comprised of changes to a method implementation (one method at time). I don't create/remove or change anything else in the method's signature or Type.

Is this line of code from ILSpy decompiler valid?

I decompiled a release assembly using ILSPy and I got code like below. When I open the decompiled project in VS 2013, I get an error for each of these statements.
using #j;//this line shows up as an error in VS2013
using System;
The error is:
Preprocessor directives must appear as the first non-whitespace character on a line
I get a similar error at following line also.
string path = #db.#ab(HttpUtility.UrlDecode(text));
Question : What is the meaning of using # and how can I correct these errors?
I have also noticed that some decompiled classes have names starting with # and so do some namespaces and method names. I have never used such a naming convention, so it's very confusing how 'ILSpy` came up with such code.
No, it's not valid C#. Chances are it's decompiled code that was obfuscated to start with, so using identifiers that are valid in IL but not in C#.
Typically, if you're decompiling obfuscated code, you're doing something against the wishes of the original authors of the code - so I'd suggest just not doing that. If you think you have a legitimate reason for getting the source code for something, ask the author.
Could you convert this into valid C#? Sure - just take every #-prefixed identifier, and map it (consistently) onto something else, e.g.
using hashj;
...
string path = hashdb.hashab(HttpUtility.UrlDecode(text));
... and eventually you'll run across a class called #db which you'd then rename to hashdb etc. But the point of the obfuscation is to make this a painful process.

Error 21 error LNK2022: metadata operation failed (80131195) : Custom attributes are not consistent: (0x0c0004c7)

I have a large windows forms project that was ported from MFC to WinForms. The business logic is all in C++ so we have a couple of assemblies written using C++/CLI to wrap the unmanaged code. The original port was done using Visual Studio 2005 and .net 2.1. We have migrated it to VS2010 and .net 4.0. We are currently maintaining both versions. Everything was fine until I added a header file for a class so I could utilize one of its methods. Just adding the header caused the error:
Error 21 error LNK2022: metadata operation failed (80131195) : Custom attributes are not consistent: (0x0c0004c7). c:\XXXX\Project\AAAAPI.obj
Project.API
There are two clases involve3 here:
AAAAAPI.cpp with header AAAAAPI.h
BBBBAPI.cpp with header BBBBAPI.h
if AAAAAPI only included AAAAPI.h
and BBBBAPI.cpp only includes BBBBAPI.h everything links and runs as expexcted
But when I add AAAAPI.h to BBBBAPI.cpp I get the above error. What is interesting is it is not compalining about BBBAPI.OBJ but AAAAPI.OBJ
Also If I remove AAAAAPI.h from BBBBAPI.h (which works as above) and add BBBBAPI.H to AAAAPI.cpp it works. So the same two headers in one cpp filr work and in another they do not work.
I hope this is enough information for you to understand my problem. The code involved it part of a very large system and it would be difficult to add more detail about what the code is doing. Just note that all I have to do is add a header file which is just a class definition, no executable code to cause the errors.
Any halp would be greatly apreciated.
I've gotten this error when I had a #define that affected a class definition, and the class definition ended up different depending on which file it was included from. Check that you don't have any #defines or similar that might be affecting your classes.
You'll have to post code if you want a firmer answer. It's impossible to diagnose code issues without seeing the code.

Define a constant with an environment variable value that is expanded during COMPILE time

In my csharp code I need to define a constant where its value is set from environment variable expansion during compile time.
In this example let's talk about any arbitrary string, such as "Hello World".
For c++ there seem to be various approaches. See the following answer, for example: https://stackoverflow.com/a/22828929
Surprisingly I wasn't able to find a similar solution for csharp.
In particular, there seems to be no way to tweak the "*.csproj" file accordingly?
PS:
As mentioned in the answer by Hans Passant below: there is some logic for "DefineConstants", but they only give you some kind of boolean flag, so you can use it for conditional statements such as "#if TESTFOO" in your source code. you will not be able to use the actual value of the environment variable.
One possible "workaround" (to dynamically generate additional source files) is described in the following answer, for example: https://stackoverflow.com/a/4453285
But I'm still looking for an official solution that is more "straight".
The C# build system does not support using environment variables strongly. Somewhat inevitable in C++ builds, its build model dates from the 1970s, but given a pass by Microsoft for C#. It does have a fantastic knack for causing build breaks when you try to rebuild your app a year or more after having finished the project. Or quickly when you try to build on another machine and its environment isn't set correctly. Having all the build config in one place is the superior solution.
But MSBuild supports them, you can refer to an environment variable with $(NAME) in the .csproj file. You can for example set a conditional compilation symbol with it, the kind you test in an #if expression. That requires editing the .csproj file by hand, use a text editor like Notepad. Locate the <DefineConstants> element, there are normally two. One for the Debug build and another for the Release build. A silly example:
<DefineConstants>DEBUG;TRACE;$(USERNAME)</DefineConstants>
And used like:
static void Main(string[] args) {
#if hpassant
Console.WriteLine("It's mine!");
#endif
Console.ReadLine();
}
Oops, testing it a bit more reveals that it also works fine from the IDE :) Project + Properties, Build tab, Conditional compilation symbols = $(USERNAME). Nice.
C# does not support preprocessor macros. The only way to generate/modify source code before the compiler sees it (that is what you want to do) are template/macro expansion engines (like mustache or t4)

Will the compiler only compile code that can get executed?

I have a class library and am using only part of it. Is there a need to delete what isn't being used in order to shrink the size of the created code (in release configuration)?
As far as I've seen, the compiler takes care of that, and removing the code doesn't change the EXE file size. Will this always be true? Removing all unneeded code would take very long, so I want to know if there's need for that.
More information: there are methods and classes in the class library that aren't called from the executing code, but are referenced by other parts of code in the class library (which themselves are never called).
No, the compiler includes the "dead" code as well. A simple reason for this is that it's not always possible to know exactly what code will and won't be executed. For example, even a private method that is never referenced could be called via reflection, and public methods could be referenced by external assemblies.
You can use a tool to help you find and remove unused methods (including ones only called by other unused methods). Try What tools and techniques do you use to find dead code? and Find unused code to get you started.
It all gets compiled. Regardless of whether it is called or not. The code may be called by an external library.
The only way to make the compiler ignore code is by using Compiler Preprocessor Directives. More about those here.
I doubt the compiler will remove anything. The fact is, the compiler can't tell what is used and what is not, as types can be instantiated and methods called by name, thanks to reflection.
Let's suppose there is a class library called Utility. You created a new project and added this class library to that project. Even if your EXE calls only 1-2 methods from the class library, it's never a good idea to delete the unreferenced code.
It would go against the principle of reusablity. Despite the fact that there would be some classes present in the library unreferenced from the EXE, it would not have any bad impact on performance or size of the program.
Determining all and only dead code is (if one makes the idealization that one has a "math world" like language) recursively undecidable, in most languages. (A few rare ones like the Blaise language are decidable.)
to the question of whether there is a "need to delete what isn't being used in order to shrink the size of the created code": i think this would only be useful to save network bandwidth. removing unused code is crucial in web applications to improve loading speeds etc.
if you're code is an exe or a library, the only reason i see to remove dead code, is to improve your code quality. so that someone looking at your code 2 years down the line won't scratch their heads wondering what it does.

Categories

Resources