Accessing VS complete solution in roslyn - c#

How can we access the complete visual studio solution from code analyzer in Roslyn?
I have been trying semantic analysis without much help.
var sol = ((Microsoft.CodeAnalysis.Diagnostics.WorkspaceAnalyzerOptions)context.Options)
.Workspace.CurrentSolution;
This is what I came up with using intellisense but this always gives a null value.

In general, you can't. Analyzers run as part of commandline builds in csc and vbc, which have no notion of Workspaces or Solutions.
We are considering adding a VS specific analyzer API that would allow access to the Solution, but for Roslyn's 1.0 release, there is no supported way to do so.

For the moment WorkspaceAnalyzerOptions is internal sealed. One can use context.Options with reflection. Hacky, but working.
Solution solution =
((HostWorkspaceServices)context
.Options
.GetType()
.GetRuntimeProperty("Services")
.GetValue(context.Options))
.Workspace
.CurrentSolution;
Note, along with it the compiler gives a warning:
RS1022 Change diagnostic analyzer type to remove all direct accesses to type(s) 'Microsoft.CodeAnalysis.Host.HostWorkspaceServices, Microsoft.CodeAnalysis.Solution, Microsoft.CodeAnalysis.Workspace'

Related

"Internal error in the expression evaluator"

I've encountered a problem in expression evaluator of visual studio 2015 that says "Internal error in the expression evaluator", after some investigations I found that this is caused by an assembly that is loaded using reflection. This assembly wouldn't throw any exceptions but after that, vs exp evaluator will fail.
This is not the only assembly that I load, there are some good working ones that don't influent the evaluator.
To overcome this issue I had to check 'Menu > options > debugging > Use Managed Compatibility Mode' but this disables the 'Edit & Continue' feature, what can I do?
Properties of the causer assembly:
its name is the same as the main assembly
(i changed its name but nothing happened)
all of my projects are using dotNet 4.5
all root namespaces are same
(all of the assemblies are so)
Thanks!
That sounds like a bug in the expression evaluator. For a better workaround, instead of checking "Use Managed Compatibility Mode", check "Use the legacy C# and VB expression evaluators". This should enable you to continue using Edit and Continue as well as other features added within the last few releases.
In terms of the "Internal error in expression evaluator", can you please open an issue by going to Help -> Send Feedback -> Report a problem? That will help us fix the problem in future releases.
Just extending on the solution provided by Patrick Nelson. For Visual Studio 2015+ as inquired, the steps are as follows.
If you're debugging at the moment, this option will be unavailable. Stop the debugger.
Go to Tools -> Options
and here under the Options select Debug -> General and scroll down to find the ...legacy C# expression.. option:
More information is provided here:
Switching to Managed Compatibility Mode
Note: There are also some serious drawbacks that occur from switching to the legacy mode. Especially Runtime Reflection of the implemented Interfaces becomes almost an impossibility or extremely inconvenient. There are also other Reflection methods which will throw errors.
I finally figured out what created this problem in my Visual Studio!
The quick fix is to delete the debug object favorites from the "Documents/Visual Studio xx/Visualizers" folder and restart Visual Studio.
When you "pin" a variable in the debugger, Visual Studio saves a 'favorite' json object for it.
It appears that there is a bug in Visual Studio which corrupts the 'favorite' for some child variables that are dynamic in nature (not exactly sure of the conditions though).
For me checking "Use Managed Compatibility Mode" option worked. I was also seeing question marks when hovering over variables, instead of properties and values
I resolved this issue by simply resetting my visual studio settings by going to: to Tools->Import and Export Settings and selecting to reset to default settings
I had the same issue with VS2019. I ended up deleting my Documents/Visual Studio 2019 folder. Hope this might help someone, one day. Cost me a day.
PS. Probably not required to delete all, and of course not your projects (if they're in there), but in my case, everything in there was autogenerated by VS.
I of course tried all solutions mentioned here, and even reinstalling VS didn't work. Refactoring the class to another name was the 'trigger' which made me think there must be some cache, despite cleaning symbols and such didnt work.
In my case I was trying to evaluate lambda expression on List<> and had such error ("Internal error in the expression evaluator"). I was using VS2015, so lambda expressions were allowed. It turns out expression evaluator was lacking of Linq library. I added
using System.Linq;
to my current class and voilĂ ! Lambda evaluated.
I encountered the "internal error in the expression evaluator" error when I was debugging in release mode instead of in debug mode. I had changed it to Release when publishing to production and forgot to change it back to Debug.
Check your use of the [DebuggerBrowsable] attribute; I found a minimal case in VisualStudio 2017 15.5 and posted it here.
In this particular case, the expression evaluator (EE) crash appears related to the [DebuggerBrowsable] attribute applied to a property overriding a field of the same name. This will account for some percentage of the cases that people are experiencing out there, but there's no way of knowing how many are due to this specific issue until it gets fixed.
The full and complete demonstration example is shown in the image (and included below for good measure)
Machine-readable copy of the code in the image:
using System;
using System.Diagnostics;
class Program { static void Main() => new _derived(); }
abstract class _base
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Object trace;
};
class _derived : _base
{
public _derived() => Debugger.Break(); // <-- vs2017 EE crash when stopped here
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
new public Object trace => base.trace;
}
In my case, I had 2 same dll files in 2 different folders (seems, one dll was not correct). Deleting the .dll and rebuilding solution solved my issue.
In my case the data I was attempting to inspect was extremely large, a string which unexpectantly had hundreds of megabytes of data in it. The issue wasn't apparent when the amount of data being inspected was reasonable.

Emit to DynamicAssembly with Roslyn RC

From many examples of compiling a Roslyn SyntaxTree, I have seen code such as:
[... create tree and compilation ...]
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("foo"), AssemblyBuilderAccess.RunAndCollect);
var module = assembly.DefineDynamicModule("foo");
var result = compilation.Emit(module);
But when I try to do this in the current Roslyn released with Visual Studio 2015 RC, I see no Emit() which takes a module. I need to write to a stream and load it into a regular AppDomain-locked Assembly.
I then see this answer from Tomas Matousek: https://stackoverflow.com/a/22977158
Where he says that this has been removed because it was "problematic".
I am having difficulty finding any other information about this on the Internet. Does anyone know if:
There is another way in Roslyn to compile into an assembly that can be garbage collected?
Or this will be supported in the final release of VS / Roslyn?
Where I should direct this question if nobody here knows (had trouble finding an official, active Roslyn forum)?
As svick and JoshVarty said in the comments, this is currently not possible. I also created an issue (https://github.com/dotnet/roslyn/issues/2621) for this that might or might not end up with some more information from the Microsoft team.

Inlining an implicitly declared out variable compiles but doesn't get Visual Studio support

Consider the following scenarios:
Works:
SemanticModel semanticModel;
document.TryGetSemanticModel(out semanticModel);
Doesn't work:
var semanticModel;
document.TryGetSemanticModel(out semanticModel);
Works:
document.TryGetSemanticModel(out SemanticModel semanticModel);
Works, BUT:
document.TryGetSemanticModel(out var semanticModel);
But: The code compiles, but there is no intellisense or documentation on hover. Is the last method considered syntactic sugar for the second one (which causes the below error) or does it more than just that?
Implicitly-typed variables must be initialized
So am I looking at a bug in the implementation or Visual Studio?
I suspect this will likely work once the C# 6 compiler is finished. Right now, it does compile, but Roslyn is still a work in progress, and intellisense has limitations in the current build.
So am I looking at a bug in the implementation or Visual Studio?
This is most likely a "bug" (really a feature that hasn't been implemented yet) in the compiler services used by Visual Studio. I would recommend filing it as an Issue in the Roslyn Codebase.

How can compilation of C# code be made to require a given language or compiler version?

How can a C# program detect it is being compiled under a version of C# that does not contain support for the language features used in that program?
The C# compiler will reject the program, and produce some error message, on encountering the features of the language it does not support. This does not address the issue, which is to state that the program is being compiled with too old a version of the C# compiler, or a C# compiler that does not support the required version of C#
Ideally, it would be as simple as
#if CS_VERSION < 3
#error CSharp 3 or later is required
#end
I don't believe you can do that with a C# file, but if you're using MSBuild then the project/solution tools version number can stop it from being built with an older version of MSBuild.
Can you give the exact context of this? One "human" solution rather than a technical one might be to try compiling the code with all the "old" versions, and create a document with: "If you get an error like this it probably means you're using the wrong version..."
Another option you might want to consider to make that even simpler is to have a single "required features" file. This would be unused by your main app, but ask users to compile that first. If it works, the rest of your build should work. If it doesn't, it's due to using the wrong version. That's likely to produce a smaller range of errors from different versions (in particular it doesn't have the problem that the compiler could list errors from different files in a random order).
According to this list of preprocessor directives, it doesn't seem possible. We usually can tell by using generics (detects 2.0), using auto properties (3.0) or dynamic (4.0)
Easy: The compiler will fail and give you an error if it can't compile the code.
There is no predefined symbol for this; you could create your own symbols and define them in your build script. Note that you can fix the language version at the project level:
Project properties -> Build -> Advanced -> Language Version:
ISO-1 is C# 1.2
ISO-2 is C# 2.0
(maps to the csc /langversion parameter)
But note that this doesn't cover everything - there are a few things that this will let through - particularly in the area of generic type inference. This is only an issue if you need to support old compilers; in which case... test with an old compiler.
For example:
int[] arr1 = { 1, 2, 3, 4, 5 };
string[] arr2 = Array.ConvertAll(arr1, delegate (int i) {return i.ToString();});
This works in .NET 3.5/ISO-2 (pseudo C# 2.0), but doesn't work in .NET 2.0 (proper C# 2.0).
Perhaps you can read the supportedRuntime element:
Then you can define the directive you want based on the supportedRuntime, using CSharpProjectConfigurationProperties3.DefineConstants.
You would create a macro in VS to use this.

Visual Studio 2008 / C# : How to find dead code in a project?

How do I find dead code in a Visual Studio 2008 C# project?
Like unused classes, unused variables or unused resources?
You can try FxCop, which is integrated in Visual Studio 2008 by the name of Code Analysis. You just have to right click the project file and 'Run Code Analysis'.
FxCop is an application that analyzes managed code assemblies (code that targets the .NET Framework common language runtime) and reports information about the assemblies, such as possible design, localization, performance, and security improvements.
The active rules can be configured in the Code Analysis section of the project properties. For example some rules relevant to the case in hand are present in Usage Rules and Performance Rules:
CA1801: Review unused parameters.
CA1811: Avoid uncalled private code.
And for greater flexibility you also write your own custom rules (Tutorial on writing your own Code Analysis rule).
Install JetBrains ReSharper which will highlight the unused code for you.
A very useful tool for this is the NDepend dependency analysis tool. You can load your Visual Studio project into this, and it will analyse the dependencies of all your assemblies, types and methods. It gives you a wealth of information on the dependenices, including (but in no way limited to!) methods/types that are not used by anything at all.
You can view the dependencies either graphically, or in a list, and can write your own custom dependency queries such as this - a simple CQL query show potentially unused methods :
SELECT
METHODS // Get me a list of methods
WHERE
MethodCa == 0 // Where their afferent coupling is zero, (afferent coupling being the number of other methods that call it)
A highly recommended tool.
Shift + F12 in VS is useful for a quick check :)
While I wouldn't recommend this for a large code base you can do a certain amount manually.
If you right click over a method or class and then select "Find Usages" you'll get an output of all places where it's referenced. Obviously this will be empty if it's not used.
For ongoing clean up I'd install ReSharper

Categories

Resources