ReportDiagnostic on Partial Classes - c#

I am modifying the default analyzer project that comes from the code analyzer template to try and get it to report at all of the declarations for a partial class.
I have modified the code to:
public override void Initialize(AnalysisContext context)
{
context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType);
}
private static void AnalyzeSymbol(SymbolAnalysisContext context)
{
var namedTypeSymbol = (INamedTypeSymbol)context.Symbol;
// Find just those named type symbols with names containing lowercase letters.
if (namedTypeSymbol.Name.ToCharArray().Any(char.IsLower))
{
foreach (var location in namedTypeSymbol.Locations)
{
// For all such symbols, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, location, namedTypeSymbol.Name);
context.ReportDiagnostic(diagnostic);
}
}
}
In two separate files, I have partial classes like this:
// File1.cs
partial class Foo
{
public string BarString;
}
// File2.cs
partial class Foo
{
public string FooBarString;
}
I put breakpoints on the ReportDiagnostic and am seeing it called for each location, but within Visual Studio it only reports diagnostics within a single file.
If I put multiple implementations of Foo in a single file (and it happens to be reporting on that files declaration) then I will see both diagnostics reported.
Am I misunderstanding how diagnostics are supposed to be reported or is this a bug? If it is a bug, is it a Roslyn problem or is it a problem with Visual Studio's consumption of Roslyn?

This is a limitation of the V1 implementation of the Visual Studio diagnostic service.
There is an issue in the Roslyn repository to track this issue:
https://github.com/dotnet/roslyn/issues/3748#issuecomment-117231706
From the response in the Github issue:
This is a known issue in the v1 implementation of the Visual Studio
IDE's diagnostic service. It currently doesn't handle analyzer
reporting diagnostics outside the document being analyzed. So, if
File1.cs has the primary definition of Foo for which AnalyzeSymbol was
invoked, then the diagnostic service only retains diagnostics reported
by the analyzer within this file.

Related

Resource files (resx) does not respect Custom Tool Namespace

In the resx properties, I changed the Custom Tool Namespace from DefaultNamespace to MyNamespace.Language and the following code is generated:
namespace MyNamespace.Language
{
public class CommentResources
{
public static global::System.Resources.ResourceManager ResourceManager {
get {
//removed code...
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DefaultNamespace.CommentResources", typeof(CommentResources).Assembly);
}
}
As you can see, only the class namespace is changed, but not the namespace passed in the ResourceManager constructor and because of that, when I instanciate ResourceManager(typeof(CommentResources)) and try to access a key, it throws MissingManifestResourceException, for example:
var manager = new ResourceManager(typeof(CommentResources));
var resource = manager.GetString("myKey");
How can I truly changed the namespace?
EDIT:
Take a look at my solution below. Whenever I create a resx file within Enviroment folder, it creates a unwanted namespace. That's what's I'm trying to avoid
I recently stumbled to the same issue.
It seems that Visual Studio 2017 generates code that creates ResourceManager from RootNamespace.SubFolder.ResourcesFileName instead of CustomToolNamespace.ResourcesFileName.
Since the code is created from the Visual Studio's Single-File Generator tool called either ResXFileCodeGenerator (for internal class) or PublicResXFileCodeGenerator (for public class) that internally uses StronglyTypedResourceBuilder class, there is no way to customize its behavior, other than implementing your own Single-File Generator as a Visual Studio extension and using it as a Generator for the EmbeddedResource.
Fortunately, there is a simpler workaround. In .csproj file, under EmbeddedResource tag, specify LogicalName tag with text value of RootNamespace.SubFolder.ResourcesFileName.resources.
In your specific case, it would look like this:
<LogicalName>DefaultNamespace.CommentResources.resources</LogicalName>

No entry sign in visual studio

Does anybody know what this sign means?
You're looking at a Debug Watch or Quick Watch Window similar to this one:
The stop sign is added when the member you're watching is marked as internal. Each access modifier has its own indicator. As you can see from the picture and the code that belongs to it:
static void Main(string[] args)
{
var test = new Test();
// put breakpoint here
}
public class Test : TestBase
{
internal int SomeNumber;
protected int FooNumber;
}
public abstract class TestBase
{
internal int AbstractInternalSomeInt;
public int OtherInt;
private byte SomeByte;
}
Notice that in the class view and in the Solution Explorer the symbol for internal members is different, it shows a heart instead:
I came across this post when searching for "visual studio solution explorer no entry symbol". In my case the symbol was presented when using the file view of solution explorer rather than class view. It turned out this was because my gitignore file had an exclusion to all files "*.userprefs" and I'd added project called "userprefs" - what are the odds!
Easy way to fix - right click the files in solution explorer and choose "Add ignored file to source control". Would be worth checking that this makes the desired change to the .gitignore file
In files view, I think it indicates the file is excluded from the build.
Maybe (as in my case) the file is directly included into something that is part of the build.
Look at properties > Excluded from build

Receive Test Run start/finish with DTE2 interface in Visual Studio extension

is there a way to subscribe to Test Explorer events in visual studio extension?
I didn't find anything like that in DTE2 interface. My goal is to trigger some function from extension when Test run completed (for the test that were ran from Test Explorer)
Thank you!
Thanks 280Z28 for your answer. Working code by using application object DTE:
using System.ComponentModel.Composition;
using Microsoft.VisualStudio.TestWindow.Extensibility;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.TestTools.Execution;
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
Microsoft.VisualStudio.OLE.Interop.IServiceProvider InteropServiceProvider = application as Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
_ServiceProvider = new ServiceProvider(InteropServiceProvider);
_ComponentModel = (IComponentModel)_ServiceProvider.GetService(typeof(SComponentModel));
_OperationState = _ComponentModel.GetService<IOperationState>();
_OperationState.StateChanged += _OperationState_StateChanged;
}
void _OperationState_StateChanged(object sender, OperationStateChangedEventArgs e)
{
}
It is also possible to access currently discovered test by ITestsService.
_TestsService = _ComponentModel.GetService<Microsoft.VisualStudio.TestWindow.Extensibility.ITestsService>();
var GetTestTask = _TestsService.GetTests();
GetTestTask.ContinueWith(Task =>
{
var DiscoveredTests = Task.Results.ToList();
});
The interfaces you need are available through MEF in the Microsoft.VisualStudio.TestWindow.Interfaces.dll assembly.
You need to expose your extension through MEF and [Import] an instance of IOperationState, or use the IComponentModel interface (returned for the SComponentModel service) to access the IOperationState. From there, you want to add an event handler to the IOperationState.StateChanged event, and look for the State property to include the TestOperationStates.TestExecutionFinished flag.
I'm terribly sorry for the lack of links, but I couldn't find any information about this in MSDN.
Edit: Two remarks about compatibility.
This is only available in Visual Studio 2012 and newer.
The necessary assembly (mentioned above) has a different strong name in the two versions of Visual Studio, and there is no bindingRedirect in Visual Studio 2013. What this means is you will be forced to deploy separate extensions for Visual Studio 2012 and Visual Studio 2013, or get "clever" about the way you dynamically load your extension code (the latter is way beyond the scope of this answer, but I've used it for some cases like Inheritance Margin extension that requires access to version-specific IntelliSense resources).
Sample VS 2017
A sample using MEF and the ITestContainerDiscoverer exported type. But be aware this may be gone in VS 2019!
[Export(typeof(ITestContainerDiscoverer))]
[Export(typeof(Testything))]
internal class Testything : ITestContainerDiscoverer
{
[ImportingConstructor]
internal Testything([Import(typeof(IOperationState))]IOperationState operationState)
{
operationState.StateChanged += OperationState_StateChanged;
}
public Uri ExecutorUri => new Uri("executor://PrestoCoverageExecutor/v1");
public IEnumerable<ITestContainer> TestContainers
{
get
{
return new ITestContainer[0].AsEnumerable();
}
}
public event EventHandler TestContainersUpdated;
private void OperationState_StateChanged(object sender, OperationStateChangedEventArgs e)
{
if (e.State == TestOperationStates.TestExecutionFinished)
{
var s = e.Operation;
}
}
}
Some more things could be found here
https://www.fuget.org/packages/Microsoft.VisualStudio.TestWindow.Interfaces/

Unable to compile code output because of some reference assembly goofups

My issue goes like this:
There is a project called myframework. It has some extension methods defined in it as follows:
namespace myframework
{
public static class Helpers
{
public static bool ContainsAll(this string obj, string[])
{
return true;
}
}
}
It also has some other stuff like interfaces, etc, etc.
There is a second class I generate via System.CodeDom classes. The generated output is somewhat like this:
using myframework;
public class A: IMyFrameworkInterface
{
public void foo()
{
string s ="HELLO";
if(s.ContainsAll(some_arr))
return;
}
//More methods defined...
}
The compiler options I pass which is created prior to the actual compile call references the correct assemblies
var cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("myframework.dll");
The code compilation modules are written in a different project. The particular class responsible for this also nicely gives us access to a list of CompilerError object via which we can learn the result of compilation.
Issue1: When I tried this in an asp.net project the compiler threw error saying it could not find metadata file myframework.dll (despite it being referenced in the project).
Issue2: When I tried it with a windows forms project. It gave a different error. This time saying that string does not contain definition for ContainsAll()
How to solve these two specific problems?
Found out the answer to this after a bit digging up. I was using .net framework 3.5. The codedom compiler apis targets v2.0 of the framework by default. Hence, you have to manually specify the correct framework:
var cp = new CompilerParameters(
new Dictionary<string,string>() { {"CompilerVersion", "v3.5"} });
For the compilation to work within an asp.net environment you'd have to actually point the references to the correct location. Hence you'd have to do something like follows:
cp.ReferencedAssemblies.Add(
HttpContext.Current.Server.MapPath(
"bin\\myframework.dll"));
My references:
http://blogs.msdn.com/b/lukeh/archive/2007/07/11/c-3-0-and-codedom.aspx
.Net 3.5 CodeDom Compiler generating odd errors
And comments in the question's post. :)

F# declared namespace is not available in the c# project or visible through the object browser

F# declared namespace is not available in the c# project or visible through the object browser.
I have built a normal F# library project, but even after i build the project and reference it to my C# project, I am unable to access the desired namespace.
I am also unable to see it in the object browser, i get an error telling me that it has not been built. I am running on the september release can someone point out my error ?
F# Version 1.9.6.0
(6) Edit : Referencing the dll directly has fixed my problem, referencing the project allows me to compile but the intellisence does not work. When the dll is directly referenced the intellisence works perfectly.
This is the code found in the .fs file
#light
namespace Soilsiu.Core
module public Process =
open System.Xml.Linq
let private xname (tag:string) = XName.Get(tag)
let private tagUrl (tag:XElement) = let attribute = tag.Attribute(xname "href")
attribute.Value
let Bookmarks(xmlFile:string) =
let xml = XDocument.Load(xmlFile)
xml.Elements <| xname "A" |> Seq.map(tagUrl)
let PrintBookmarks (xmlFile:string) =
let list = Bookmarks(xmlFile)
list |> Seq.iter(fun u -> printfn "%s" u)
(5) Edit : Could ReSharper 4.0 be the problem?
(4) Edit : When i say the Object browser is unable to read the resulting assembly, i mean that when I try to open the assembly in the object browser i get an error telling me the project has not yet been built. yet again i can read the assembly using reflector.
(3) Edit : Reflector can Disassemble the dll but the Object Browser is unable to read it.
(2) Edit : I have Upgraded my F# version to 1.9.6.2 and still the same consequence
(1) Edit : I was able to Disassemble the dll to C# I get : (Everything seems to be fine here)
namespace Soilsiu.Core
{
[CompilationMapping(7)]
public static class Crawler
[CompilationMapping(7)]
public static class Process
}
[CompilationMapping(7)]
public static class Process
{
// Methods
static Process();
public static IEnumerable<string> Bookmarks(string xmlFile);
public static void PrintBookmarks(string xmlFile);
internal static string tagUrl(XElement tag);
internal static XName xname(string tag);
// Nested Types
[Serializable]
internal class clo#13 : FastFunc<XElement, string>
{
// Methods
public clo#13();
public override string Invoke(XElement tag#9);
}
[Serializable]
internal class clo#17 : FastFunc<string, Unit>
{
// Methods
public clo#17();
public override Unit Invoke(string u);
}
}
What if you reference the produced DLL directly (i.e., not via a project reference, but via a file reference)?
Maybe IntelliSense is just messed up? What compiler error do you get when you try to use it in C#? When you say "the object browser is unable to read it" what does that mean?
For what it's worth, I added this to a F# library project, referenced it (project) from a C# console app, and was able to use it. IntelliSense did not work at first though. (Had to rebuild.)
If you can make a solid repro, I'd suggest emailing it to F# bugs alias (fsbugs).
I tried the same thing. It looks as if Visual Studio and Resharper 4.0 doesn't understand F# for some reason. If you ignore the sea of red text and the lack of intellisense, it will compile fine.
Try
Make sure that C# project is targeted FULL .NET (NOT Client Profile).
Add references to assemblies into C# project which are used by F# project.

Categories

Resources