VS Code C# syntax highlighting bug - c#

using "Visual Studio Code 1.15.1";
I've been using VSCode on my Mac to view some C# code I had written elsewhere, and for some reason, certain things aren't highlighted correctly.
(0) await statements are not highlighted correctly when used with a variable instead of a method call or member accessor.
await someTask; // highlighted as if someTask were a variable of type await
await someThing.SomeTask; // highlighted correctly
await someThing.DoSomething(); // highlighted correctly
(1) using is highlighted as if it were a function instead of a keyword.
using (var spoon = new DisposableSpoon()) {
// ...
}
which didn't happen before.
(2) Some C# 7 features aren't highlighted correctly, such as out variables.
if (map.TryGetValue(key, out TValue val)) {
// ...
}
I'm using the default theme (Dark+), and I don't think I have any major, workspace-breaking plugins enabled (most are just extra themes or support for other languages). Did I accidentally mess up a config or something, or is this a bug?
Edit: (1) is fixed when I change the language from "C#" to "C# (official)". There seem to be multiple C#'s for some reason, but none seem to fix all of the aforementioned bugs. If this is just due to a wonky config or something, how would I revert to default?

The await issue seems like a bug in our built-in c# grammar. I've opened an issue with the grammar we use to track this: https://github.com/dotnet/csharp-tmLanguage/issues/83
I can only repo (1) when not within a class or method body, and I can't repo (2). Can you please file issues for these as well. Include the code, a screenshot, and a short explanation of what looks incorrect: https://github.com/dotnet/csharp-tmLanguage/issues/new

Related

Creating an extension method for HtmlHelper that takes an Action<T> causing auto formatting issues in VS 2017

Current code
I have created an extension method for HtmlHelper that is defined as follows:
public static IHtmlString MyMethod(this HtmlHelper helper, Action<MyClass> action)
{
MyClass settings = new MyClass();
action(settings);
// Here I can now use the settings as defined in razor view.
}
The purpose of creating the extension method in this way is so that I can call it by allowing the MyClass class to be defined in the razor view like this:
<div>
#Html.MyMethod(settings =>
{
settings.SomeFunction(1, 2, 3);
})
</div>
The problem
Now this works great and does exactly what I expect. However, the 1 issue is that every time I do "Format Document" (Ctrl + E, D) in Visual Studio, all lines after the first line get indented another tab. Just to be clear, after formatting the document 4 times it would look something like this:
<div>
#Html.MyMethod(settings =>
{
settings.SomeFunction(1, 2, 3);
})
</div>
It seems that the problem only happens when used inside an element (in this example div). But that is something that I would need to be able to use.
In a view that I am modifying often it does't take long until I have auto formatted them off the visible screen space. I then need to manually move them back. Needless to say this is very annoying, especially when used multiple times in a single view.
I am currently using Visual Studio 2017, I am not sure if this problem exists in previous versions or not.
What I have tried
I have tried different ways of writing the code in an attempt to stop it, but it always formats to the same problem. So for example I moving the settings to the 2nd line, move the opening { to the first line. Nothing seems to work. A couple of examples:
#Html.MyMethod(
settings =>
{
settings.SomeFunction(1, 2, 3);
})
#Html.MyMethod(settings => {
settings.SomeFunction(1, 2, 3);
})
The question
Why is this happening, and what can I do to stop it? I am open to redefining the extension method if that is the problem, as long as I can call it in the same way I have shown above.
Just a note, for anyone that has used DevExpress MVC library, that allows similar functionality but somehow that doesn't seem to suffer from this particular problem. I don't know what they have done differently though, I just know somehow this functionality should be achievable without causing this formatting problem.
The formatter for Razor files is terrible. The issues you mention seem fairly mild - it can get far worse. This is a long-standing problem which predates MVC; the formatter for ASPX pages was just as bad.
Razor files are a mixture of 5 languages, each of which have different formatting needs:
HTML
CSS
JavaScript
C# or Visual Basic
Razor
Perhaps it is forgivable that Microsoft have not got the formatting right in every situation. Actually i think they have given up trying.
To fix the formatting problems, I would suggest pressing Control-Z immediately after it formats incorrectly. That will undo the formatting, without undoing the change which triggered it.

Listening to Map Entries with Predicates doesn't fire

I try to use map listener with predicates like on docs.
I am using .net 3.9 client and I configured my Java (also Hazelcast 3.9) code. But my listeners doesn't fire.
myTestMap.AddEntryListener(new EntryAdapter<string,MyTestMap> { Added = e => ValidateData(e) },new SqlPredicate("Status=2"),true);
When old value does not match predicate, new value matches predicate
writes on document. But any event fire include with have no predicate.
UPDATE: I update version 3.9.1 and try to use EntryAddedListener.
I update code;
myTestMap.AddEntryListener(new TestListener(),new SqlPredicate("Status=2"),true);
public class TestListener: EntryAddedListener<string,MyTestMap> {
public void EntryAdded(EntryEvent<string,MyTestMap> #event) {
ValidateData(#event);
}
}
This time, I get:
Your app has entered a break state, but there is no code to show because all threads were executing external code (typically system or framework code).
UPDATE 2: Ok, I found the problem and try to fix it.
ClientMapProxy.AddEntryListener(MapListener listener,.....
methods has recursive call so, I get previous exception.
You're usage is exactly correct and is expected to work. From looking at our Github repository, I see you've already figured it really is a bug and reported it (https://github.com/hazelcast/hazelcast-csharp-client/issues/145) thanks for it.
For the sake of others running into the same issue, we're looking into fixing it, please see the issue linked above.
Thanks again for the report and your digging into it!

Mobile apps: is it a good practice to use a constant to distinguish the Free/Pro version?

I have two apps which do essentially the same, with small differences (different logo, ads hidden in the Pro, different Facebook app id for the login flow, etc.)
Currently, I use a
public const bool isProVersion = false;
Which I toggle before compiling, and it changes the whole app behavior depending on its value.
The only issue is that I have a lot of "unreachable code detected" notices in my error list.
This is intended, because some code must never be reached in that version, but it doesn't look very clean.
I could use a static variable instead of a constant, but this will make, for example, the ads code compiled and "reachable" into the Pro version, which is not needed and could lower the performance.
Is there any better alternative?
Expanding on the comment by Jeroen Vannevel, you really should use preprocessor directives. You should use an ISPROVERSION directive and two compiling configurations, one that defines ISPROVERSION (the pro configuration) and one that doesn't (the free configuration).
So, instead of doing this:
if (YourClassName.isProVersion)
{
// user has paid, yey!
SomeClass.LoadAds(false);
}
else
{
// user didn't pay, scr** them!
SomeClass.LoadAds(true);
}
You would be doing something like this:
#if ISPROVERSION
// user has paid, yey!
SomeClass.LoadAds(false);
#else
// user didn't pay, scr** them!
SomeClass.LoadAds(true);
#endif
This way, if you build using the pro configuration, the code in the #else statements won't even be compiled.
Read more about defining preprocessor directives here: /define (C# Compiler Options)

Visual Studio debugging "quick watch" tool and lambda expressions

Why can't I use lambda expressions while debugging in “Quick watch” window?
UPD: see also
Link
Link
No you cannot use lambda expressions in the watch / locals / immediate window. As Marc has pointed out this is incredibly complex. I wanted to dive a bit further into the topic though.
What most people don't consider with executing an anonymous function in the debugger is that it does not occur in a vaccuum. The very act of defining and running an anonymous function changes the underlying structure of the code base. Changing the code, in general, and in particular from the immediate window, is a very difficult task.
Consider the following code.
void Example() {
var v1 = 42;
var v2 = 56;
Func<int> func1 = () => v1;
System.Diagnostics.Debugger.Break();
var v3 = v1 + v2;
}
This particular code creates a single closure to capture the value v1. Closure capture is required whenever an anonymous function uses a variable declared outside it's scope. For all intents and purposes v1 no longer exists in this function. The last line actually looks more like the following
var v3 = closure1.v1 + v2;
If the function Example is run in the debugger it will stop at the Break line. Now imagine if the user typed the following into the watch window
(Func<int>)(() => v2);
In order to properly execute this the debugger (or more appropriate the EE) would need to create a closure for variable v2. This is difficult but not impossible to do.
What really makes this a tough job for the EE though is that last line. How should that line now be executed? For all intents and purposes the anonymous function deleted the v2 variable and replaced it with closure2.v2. So the last line of code really now needs to read
var v3 = closure1.v1 + closure2.v2;
Yet to actually get this effect in code requires the EE to change the last line of code which is actually an ENC action. While this specific example is possible, a good portion of the scenarios are not.
What's even worse is executing that lambda expression shouldn't be creating a new closure. It should actually be appending data to the original closure. At this point you run straight on into the limitations ENC.
My small example unfortunately only scratches the surface of the problems we run into. I keep saying I'll write a full blog post on this subject and hopefully I'll have time this weekend.
Lambda expressions, like anonymous methods, are actually very complex beasts. Even if we rule out Expression (.NET 3.5), that still leaves a lot of complexity, not least being captured variables, which fundamentally re-structure the code that uses them (what you think of as variables become fields on compiler-generated classes), with a bit of smoke and mirrors.
As such, I'm not in the least surprised that you can't use them idly - there is a lot of compiler work (and type generation behind the scenes) that supports this magic.
You can't use lambda expressions in the Immediate or Watch windows.
You can however use System.Linq.Dynamic expressions, which take the form .Where("Id = #0", 2) - it doesn't have the full range of methods available in standard Linq, and doesn't have the full power of lambda expressions, but still, it's better than nothing!
The future has come!
Support for debugging lambda expressions has been added to Visual Studio 2015 (Preview at the time of writing).
Expression Evaluator had to be rewritten, so many features are missing: remote debugging ASP.NET, declaring variables in Immediate window, inspecting dynamic variables etc. Also lambda expressions that require calls to native functions aren't currently supported.
this might help:
Extended Immediate Window for Visual Studio (use Linq, Lambda Expr in Debugging)
http://extendedimmediatewin.codeplex.com/
http://dvuyka.spaces.live.com/blog/cns!305B02907E9BE19A!381.entry
All the best,
Patrick
Lambda expressions are not supported by the debugger's expression evaluator... which is hardly surprising since at compile time they are used to create methods (or Expression Trees) rather than expressions (take a look in Reflector with the display switched to .NET 2 to see them).
Plus of course they could form a closure, another whole layer of structure.
In VS 2015 you can do so now,this is one of the new feature they added.
If you still need to use Visual Studio 2013, you can actually write a loop, or lambda expression in the immediate window using also the package manager console window. In my case, I added a list at the top of the function:
private void RemoveRoleHierarchy()
{
#if DEBUG
var departments = _unitOfWork.DepartmentRepository.GetAll().ToList();
var roleHierarchies = _unitOfWork.RoleHierarchyRepository.GetAll().ToList();
#endif
try
{
//RoleHierarchy
foreach (SchoolBo.RoleHierarchy item in _listSoRoleHierarchy.Where(r => r.BusinessKeyMatched == false))
_unitOfWork.RoleHierarchyRepository.Remove(item.Id);
_unitOfWork.Save();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
throw;
}
}
Where my GetAll() function is:
private DbSet<T> _dbSet;
public virtual IList<T> GetAll()
{
List<T> list;
IQueryable<T> dbQuery = _dbSet;
list = dbQuery
.ToList<T>();
return list;
}
Here I kept getting the following error, so I wanted to print out all the items in the various repositories:
InnerException {"The DELETE statement conflicted with the REFERENCE constraint \"FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId\". The conflict occurred in database \"CC_Portal_SchoolObjectModel\", table \"dbo.Department\", column 'OranizationalRoleId'.\r\nThe statement has been terminated."} System.Exception {System.Data.SqlClient.SqlException}
Then, I find out how many records are in the department repository by executing this in the immediate window:
_unitOfWork.DepartmentRepository.GetAll().ToList().Count
Which returned 243.
So, if you execute the following in the package manager console, it prints out all the items:
PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }
The author for the idea can be found here
To answer your question, here's the Visual Studio Program Manager's official explanation of why you can't do this. In short, because "it's really, really hard" to implement in VS. But the feature is currently in progress (as updated on Aug 2014).
Allow the evaluation of lambda expressions while debugging
Add your vote while you're there!

How do you flag code so that you can come back later and work on it?

In C# I use the #warning and #error directives,
#warning This is dirty code...
#error Fix this before everything explodes!
This way, the compiler will let me know that I still have work to do. What technique do you use to mark code so you won't forget about it?
Mark them with // TODO, // HACK or other comment tokens that will show up in the task pane in Visual Studio.
See Using the Task List.
Todo comment as well.
We've also added a special keyword NOCHECKIN, we've added a commit-hook to our source control system (very easy to do with at least cvs or svn) where it scans all files and refuses to check in the file if it finds the text NOCHECKIN anywhere.
This is very useful if you just want to test something out and be certain that it doesn't accidentaly gets checked in (passed the watchful eyes during the diff of everything thats commited to source control).
I use a combination of //TODO: //HACK: and throw new NotImplementedException(); on my methods to denote work that was not done. Also, I add bookmarks in Visual Studio on lines that are incomplete.
//TODO: Person's name - please fix this.
This is in Java, you can then look at tasks in Eclipse which will locate all references to this tag, and can group them by person so that you can assign a TODO to someone else, or only look at your own.
If I've got to drop everything in the middle of a change, then
#error finish this
If it's something I should do later, it goes into my bug tracker (which is used for all tasks).
'To do' comments are great in theory, but not so good in practice, at least in my experience. If you are going to be pulled away for long enough to need them, then they tend to get forgotten.
I favor Jon T's general strategy, but I usually do it by just plain breaking the code temporarily - I often insert a deliberately undefined method reference and let the compiler remind me about what I need to get back to:
PutTheUpdateCodeHere();
An approach that I've really liked is "Hack Bombing", as demonstrated by Oren Eini here.
try
{
//do stuff
return true;
}
catch // no idea how to prevent an exception here at the moment, this make it work for now...
{
if (DateTime.Today > new DateTime(2007, 2, 7))
throw new InvalidOperationException("fix me already!! no catching exceptions like this!");
return false;
}
Add a test in a disabled state. They show up in all the build reports.
If that doesn't work, I file a bug.
In particular, I haven't seen TODO comments ever decrease in quantity in any meaningful way. If I didn't have time to do it when I wrote the comment, I don't know why I'd have time later.
//TODO: Finish this
If you use VS you can setup your own Task Tags under Tools>Options>Environment>Task List
gvim highlights both "// XXX" and "// TODO" in yellow, which amazed me the first time I marked some code that way to remind myself to come back to it.
I'm a C++ programmer, but I imagine my technique could be easily implemented in C# or any other language for that matter:
I have a ToDo(msg) macro that expands into constructing a static object at local scope whose constructor outputs a log message. That way, the first time I execute unfinished code, I get a reminder in my log output that tells me that I can defer the task no longer.
It looks like this:
class ToDo_helper
{
public:
ToDo_helper(const std::string& msg, const char* file, int line)
{
std::string header(79, '*');
Log(LOG_WARNING) << header << '\n'
<< " TO DO:\n"
<< " Task: " << msg << '\n'
<< " File: " << file << '\n'
<< " Line: " << line << '\n'
<< header;
}
};
#define TODO_HELPER_2(X, file, line) \
static Error::ToDo_helper tdh##line(X, file, line)
#define TODO_HELPER_1(X, file, line) TODO_HELPER_2(X, file, line)
#define ToDo(X) TODO_HELPER_1(X, __FILE__, __LINE__)
... and you use it like this:
void some_unfinished_business() {
ToDo("Take care of unfinished business");
}
It's not a perfect world, and we don't always have infinite time to refactor or ponder the code.
I sometimes put //REVIEW in the code if it's something I want to come back to later. i.e. code is working, but perhaps not convinced it's the best way.
// REVIEW - RP - Is this the best way to achieve x? Could we use algorithm y?
Same goes for //REFACTOR
// REFACTOR - should pull this method up and remove near-dupe code in XYZ.cs
I use // TODO: or // HACK: as a reminder that something is unfinished with a note explaining why.
I often (read 'rarely') go back and finish those things due to time constraints.
However, when I'm looking over the code I have a record of what was left uncompleted and more importantly WHY.
One more comment I use often at the end of the day or week:
// START HERE CHRIS
^^^^^^^^^^^^^^^^^^^^
Tells me where I left off so I can minimize my bootstrap time on Monday morning.
// TODO: <explanation>
if it's something that I haven't gotten around to implementing, and don't want to forget.
// FIXME: <explanation>
if it's something that I don't think works right, and want to come back later or have other eyes look at it.
Never thought of the #error/#warning options. Those could come in handy too.
I use //FIXME: xxx for broken code, and //CHGME: xxx for code that needs attention but works (perhaps only in a limited context).
Todo Comment.
These are the three different ways I have found helpful to flag something that needs to be addressed.
Place a comment flag next to the code that needs to be looked at. Most compilers can recognize common flags and display them in an organized fashion. Usually your IDE has a watch window specifically designed for these flags. The most common comment flag is: //TODO This how you would use it:
//TODO: Fix this before it is released. This causes an access violation because it is using memory that isn't created yet.
One way to flag something that needs to be addressed before release would be to create a useless variable. Most compilers will warn you if you have a variable that isn't used. Here is how you could use this technique:
int This_Is_An_Access_Violation = 0;
IDE Bookmarks. Most products will come with a way to place a bookmark in your code for future reference. This is a good idea, except that it can only be seen by you. When you share your code most IDE's won't share your bookmarks. You can check the help file system of your IDE to see how to use it's bookmarking features.
I also use TODO: comments. I understand the criticism that they rarely actually get fixed, and that they'd be better off reported as bugs. However, I think that misses a couple points:
I use them most during heavy development, when I'm constantly refactoring and redesigning things. So I'm looking at them all the time. In situations like that, most of them actually do get addressed. Plus it's easy to do a search for TODO: to make sure I didn't miss anything.
It can be very helpful for people reading your code, to know the spots that you think were poorly written or hacked together. If I'm reading unfamiliar code, I tend to look for organizational patterns, naming conventions, consistent logic, etc.. If that consistency had to be violated one or two times for expediency, I'd rather see a note to that effect. That way I don't waste time trying to find logic where there is none.
If it's some long term technical debt, you can comment like:
// TODO: This code loan causes an annual interest rate of 7.5% developer/hour. Upfront fee as stated by the current implementation. This contract is subject of prior authorization from the DCB (Developer's Code Bank), and tariff may change without warning.
... err. I guess a TODO will do it, as long as you don't simply ignore them.
This is my list of temporary comment tags I use:
//+TODO Usual meaning.
//+H Where I was working last time.
//+T Temporary/test code.
//+B Bug.
//+P Performance issue.
To indicate different priorities, e.g.: //+B vs //+B+++
Advantages:
Easy to search-in/remove-from the code (look for //+).
Easy to filter on a priority basis, e.g.: search for //+B to find all bugs, search for //+B+++ to only get high priority ones.
Can be used with C++, C#, Java, ...
Why the //+ notation? Because the + symbol looks like a little t, for temporary.
Note: this is not a Standard recommendation, just a personal one.
As most programmers seem to do here, I use TODO comments. Additionally, I use Eclipse's task interface Mylyn. When a task is active, Mylyn remembers all resources I have opened. This way I can track
where in a file I have to do something (and what),
in which files I have to do it, and
to what task they are related.
Besides keying off the "TODO:" comment, many IDE's also key off the "TASK:" comment. Some IDE's even let you configure your own special identifier.
It is probably not a good idea to sprinkle your code base with uninformative TODOs, especially if you have multiple contributors over time. This can be quite confusing to the newcomers. However, what seems to me to work well in practice is to state the author and when the TODO was written, with a header (50 characters max) and a longer body.
Whatever you pack into the TODO comments, I'd recommend to be systematic in how you track them. For example, there is a service that examines the TODO comments in your repository based on git blame (http://www.tickgit.com).
I developed my own command-line tool to enforce the consistent style of the TODO comments using ideas from the answers here (https://github.com/mristin/opinionated-csharp-todos). It was fairly easy to integrate it into the continuous integration so that the task list is re-generated on every push to the master.
It also makes sense to have the task list separate from your IDE for situations when you discuss the TODOs in a meeting with other people, when you want to share it by email etc.

Categories