diff --git a/.gitignore b/.gitignore
index 25fac6ae83fb2..9ea10718c520f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,6 +38,7 @@ UnitTestResults.html
*.tmp
*.tmp_proj
*.log
+*.wrn
*.vspscc
*.vssscc
.builds
diff --git a/build/VSL.Imports.Closed.targets b/build/VSL.Imports.Closed.targets
index 1376cc60e1d03..a853bdca6e337 100644
--- a/build/VSL.Imports.Closed.targets
+++ b/build/VSL.Imports.Closed.targets
@@ -1,4 +1,34 @@
+
+
+
+
+ $(IntermediateOutputPath)$(TargetFileName).pcbm
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+ true
+ true
+
+
+
+
+
+
+
+
+
- $(CompileDependsOn);ApplyOptimizations
- $(CleanDependsOn);CleanApplyOptimizations;CleanPhoneCopy
+ $(CleanDependsOn);CleanPhoneCopy
-
- true
- true
- $(CompileDependsOn);FakeSignAssembly
- $(IntermediateOutputPath)$(TargetFileName).fakesign
-
-
-
-
-
-
-
-
-
$(CreateVsixContainerDependsOn);SignVsixInputs
$(PrepareForRunDependsOn);SignVsix
true
-
+
diff --git a/docs/specs/PortablePdb-Metadata.md b/docs/specs/PortablePdb-Metadata.md
index 93a0f14b287a8..3a4032ad6e03f 100644
--- a/docs/specs/PortablePdb-Metadata.md
+++ b/docs/specs/PortablePdb-Metadata.md
@@ -373,6 +373,19 @@ Structure:
TODO: Bit ordering.
+##### Root Namespace (VB compiler)
+Parent: Module
+
+Kind: {58b2eab6-209f-4e4e-a22c-b2d0f910c782}
+
+Structure:
+
+ Blob ::= namespace
+
+| terminal | encoding | description|
+|:---------|:---------|:-----------|
+| _namespace_ | UTF8 string | The root namespace. |
+
##### Edit and Continue Local Slot Map (C# & VB compilers)
Parent: MethodDef
diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
index e4f2cfb97d156..0f4cb36e60db3 100644
--- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
@@ -2283,25 +2283,6 @@ internal override CommonPEModuleBuilder CreateModuleBuilder(
CompilationTestData testData,
DiagnosticBag diagnostics,
CancellationToken cancellationToken)
- {
- return this.CreateModuleBuilder(
- emitOptions,
- manifestResources,
- assemblySymbolMapper,
- testData,
- diagnostics,
- ImmutableArray.Empty,
- cancellationToken);
- }
-
- internal CommonPEModuleBuilder CreateModuleBuilder(
- EmitOptions emitOptions,
- IEnumerable manifestResources,
- Func assemblySymbolMapper,
- CompilationTestData testData,
- DiagnosticBag diagnostics,
- ImmutableArray additionalTypes,
- CancellationToken cancellationToken)
{
// Do not waste a slot in the submission chain for submissions that contain no executable code
// (they may only contain #r directives, usings, etc.)
@@ -2326,8 +2307,6 @@ internal CommonPEModuleBuilder CreateModuleBuilder(
PEModuleBuilder moduleBeingBuilt;
if (_options.OutputKind.IsNetModule())
{
- Debug.Assert(additionalTypes.IsEmpty);
-
moduleBeingBuilt = new PENetModuleBuilder(
(SourceModuleSymbol)SourceModule,
emitOptions,
@@ -2343,8 +2322,7 @@ internal CommonPEModuleBuilder CreateModuleBuilder(
kind,
moduleProps,
manifestResources,
- assemblySymbolMapper,
- additionalTypes);
+ assemblySymbolMapper);
}
// testData is only passed when running tests.
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
index 1d72ca569db15..6962133bddabd 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
@@ -603,8 +603,9 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
AsyncStateMachine stateMachineType;
- // In case of async lambdas, the method has already been uniquely named, so there is no need to
- // produce a unique method ordinal for the corresponding state machine type, whose name includes the (unique) method name.
+ // Synthesized methods have no ordinal stored in custom debug information (only user-defined methods have ordinals).
+ // In case of async lambdas, which synthesize a state machine type during the following rewrite, the containing method has already been uniquely named,
+ // so there is no need to produce a unique method ordinal for the corresponding state machine type, whose name includes the (unique) containing method name.
const int methodOrdinal = -1;
BoundStatement bodyWithoutAsync = AsyncRewriter.Rewrite(methodWithBody.Body, method, methodOrdinal, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out stateMachineType);
diff --git a/src/Compilers/CSharp/Portable/Compiler/TypeCompilationState.cs b/src/Compilers/CSharp/Portable/Compiler/TypeCompilationState.cs
index 0325c25a809fd..40274c76ca52a 100644
--- a/src/Compilers/CSharp/Portable/Compiler/TypeCompilationState.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/TypeCompilationState.cs
@@ -47,8 +47,11 @@ internal MethodWithBody(MethodSymbol method, BoundStatement body, ImportChain im
/// only need one wrapper to call it non-virtually.
///
private Dictionary _wrappers;
-
- private readonly NamedTypeSymbol _type;
+
+ ///
+ /// Type symbol being compiled, or null if we compile a synthesized type that doesn't have a symbol (e.g. PrivateImplementationDetails).
+ ///
+ private readonly NamedTypeSymbol _typeOpt;
///
/// The builder for generating code, or null if not in emit phase.
@@ -65,10 +68,10 @@ internal MethodWithBody(MethodSymbol method, BoundStatement body, ImportChain im
public LambdaFrame staticLambdaFrame;
- public TypeCompilationState(NamedTypeSymbol type, CSharpCompilation compilation, PEModuleBuilder moduleBuilderOpt)
+ public TypeCompilationState(NamedTypeSymbol typeOpt, CSharpCompilation compilation, PEModuleBuilder moduleBuilderOpt)
{
this.Compilation = compilation;
- _type = type;
+ _typeOpt = typeOpt;
this.ModuleBuilderOpt = moduleBuilderOpt;
}
@@ -80,9 +83,8 @@ public NamedTypeSymbol Type
get
{
// NOTE: currently it can be null if only private implementation type methods are compiled
- // TODO: is it used? if yes, make sure it is not accessed when type is not available;
- Debug.Assert((object)_type != null);
- return _type;
+ Debug.Assert((object)_typeOpt != null);
+ return _typeOpt;
}
}
diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs
index fea5886589b2a..0192c37f247d4 100644
--- a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs
+++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs
@@ -223,9 +223,8 @@ public PEAssemblyBuilder(
OutputKind outputKind,
ModulePropertiesForSerialization serializationProperties,
IEnumerable manifestResources,
- Func assemblySymbolMapper = null,
- ImmutableArray additionalTypes = default(ImmutableArray))
- : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, assemblySymbolMapper, additionalTypes)
+ Func assemblySymbolMapper = null)
+ : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, assemblySymbolMapper, ImmutableArray.Empty)
{
}
diff --git a/src/Compilers/Core/Portable/CodeAnalysis.csproj b/src/Compilers/Core/Portable/CodeAnalysis.csproj
index 0af79898f6805..849f11c5f86d9 100644
--- a/src/Compilers/Core/Portable/CodeAnalysis.csproj
+++ b/src/Compilers/Core/Portable/CodeAnalysis.csproj
@@ -51,6 +51,9 @@
..\CodeAnalysisRules.ruleset
+
+ MetadataReader\MetadataReaderPdbExtensions.cs
+
diff --git a/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs b/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs
index 4d36f6c3db7c7..e5c370a9c0ff1 100644
--- a/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs
+++ b/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs
@@ -34,13 +34,18 @@ private SimpleDiagnostic(
if ((warningLevel == 0 && severity != DiagnosticSeverity.Error) ||
(warningLevel != 0 && severity == DiagnosticSeverity.Error))
{
- throw new ArgumentException("warningLevel");
+ throw new ArgumentException(nameof(warningLevel));
+ }
+
+ if(descriptor == null)
+ {
+ throw new ArgumentNullException(nameof(descriptor));
}
_descriptor = descriptor;
_severity = severity;
_warningLevel = warningLevel;
- _location = location;
+ _location = location ?? Location.None;
_additionalLocations = additionalLocations == null ? SpecializedCollections.EmptyReadOnlyList() : additionalLocations.ToImmutableArray();
_messageArgs = messageArgs ?? SpecializedCollections.EmptyArray
-
@@ -107,4 +106,4 @@
-
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/CSharp/Design/CodeFixes/CA1001CSharpCodeFixProvider.cs b/src/Diagnostics/FxCop/CSharp/Design/CodeFixes/CA1001CSharpCodeFixProvider.cs
deleted file mode 100644
index 0c115068b41e1..0000000000000
--- a/src/Diagnostics/FxCop/CSharp/Design/CodeFixes/CA1001CSharpCodeFixProvider.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System.Composition;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Formatting;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Design;
-using Microsoft.CodeAnalysis.Simplification;
-
-namespace Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers.Design
-{
- ///
- /// CA1001: Types that own disposable fields should be disposable
- ///
- [ExportCodeFixProvider(LanguageNames.CSharp, Name = CA1001DiagnosticAnalyzer.RuleId), Shared]
- public class CA1001CSharpCodeFixProvider : CA1001CodeFixProviderBase
- {
- internal override Task GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken)
- {
- //// We are going to implement IDisposable interface:
- ////
- //// public void Dispose()
- //// {
- //// throw new NotImplementedException();
- //// }
-
- var syntaxNode = nodeToFix as ClassDeclarationSyntax;
- if (syntaxNode == null)
- {
- return Task.FromResult(document);
- }
-
- var statement = CreateThrowNotImplementedStatement(model);
- if (statement == null)
- {
- return Task.FromResult(document);
- }
-
- var member = CreateSimpleMethodDeclaration(CA1001DiagnosticAnalyzer.Dispose, statement);
- var newNode =
- syntaxNode.BaseList != null ?
- syntaxNode.AddBaseListTypes(SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName(CA1001DiagnosticAnalyzer.IDisposable))).AddMembers(new[] { member }) :
- syntaxNode.AddBaseListTypes(SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName(CA1001DiagnosticAnalyzer.IDisposable))).AddMembers(new[] { member }).WithIdentifier(syntaxNode.Identifier.WithTrailingTrivia(SyntaxFactory.Space));
- newNode = newNode.WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation);
- return Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode(nodeToFix, newNode)));
- }
-
- protected StatementSyntax CreateThrowNotImplementedStatement(SemanticModel model)
- {
- var exceptionType = model.Compilation.GetTypeByMetadataName(NotImplementedExceptionName);
- if (exceptionType == null)
- {
- // If we can't find the exception, we can't generate anything.
- return null;
- }
-
- return SyntaxFactory.ThrowStatement(
- SyntaxFactory.ObjectCreationExpression(
- SyntaxFactory.Token(SyntaxKind.NewKeyword),
- SyntaxFactory.IdentifierName(exceptionType.Name),
- SyntaxFactory.ArgumentList(),
- null));
- }
-
- protected MethodDeclarationSyntax CreateSimpleMethodDeclaration(string name, StatementSyntax statement)
- {
- return SyntaxFactory.MethodDeclaration(
- new SyntaxList(),
- SyntaxFactory.TokenList(new SyntaxToken[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword) }),
- SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)),
- null,
- SyntaxFactory.Identifier(name),
- null,
- SyntaxFactory.ParameterList(),
- new SyntaxList(),
- SyntaxFactory.Block(statement),
- new SyntaxToken());
- }
- }
-}
diff --git a/src/Diagnostics/FxCop/Core/Design/CodeFixes/CA1001CodeFixProviderBase.cs b/src/Diagnostics/FxCop/Core/Design/CodeFixes/CA1001CodeFixProviderBase.cs
deleted file mode 100644
index 620ef3d6b546e..0000000000000
--- a/src/Diagnostics/FxCop/Core/Design/CodeFixes/CA1001CodeFixProviderBase.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System.Collections.Immutable;
-
-namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
-{
- ///
- /// CA1001: Types that own disposable fields should be disposable
- ///
- public abstract class CA1001CodeFixProviderBase : CodeFixProviderBase
- {
- protected const string NotImplementedExceptionName = "System.NotImplementedException";
- protected const string IDisposableName = "System.IDisposable";
-
- public sealed override ImmutableArray FixableDiagnosticIds
- {
- get { return ImmutableArray.Create(CA1001DiagnosticAnalyzer.RuleId); }
- }
-
- protected sealed override string GetCodeFixDescription(Diagnostic diagnostic)
- {
- return FxCopFixersResources.ImplementIDisposableInterface;
- }
- }
-}
diff --git a/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj b/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj
index d6e63e8122de2..36d58d9908f4f 100644
--- a/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj
+++ b/src/Diagnostics/FxCop/Core/FxCopRulesDiagnosticAnalyzers.csproj
@@ -103,7 +103,6 @@
-
@@ -112,7 +111,6 @@
-
@@ -195,4 +193,4 @@
-
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/CSharpSystemRuntimeAnalyzers.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/CSharpSystemRuntimeAnalyzers.csproj
new file mode 100644
index 0000000000000..0650326d5e7c5
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/CSharpSystemRuntimeAnalyzers.csproj
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+ 12.0
+ Debug
+ AnyCPU
+ {A36451EC-1127-40CE-B841-47F393D24624}
+ Library
+ true
+ System.Runtime.CSharp.Analyzers
+ System.Runtime.CSharp.Analyzers
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Profile7
+ .NETPortable
+ true
+
+
+
+
+
+
+
+
+ {1ee8cad3-55f9-4d91-96b2-084641da9a6c}
+ CodeAnalysis
+
+
+ {b501a547-c911-4a05-ac6e-274a50dff30e}
+ CSharpCodeAnalysis
+
+
+ {5f8d2414-064a-4b3a-9b42-8e2a04246be5}
+ Workspaces
+
+
+ {baa0fee4-93c8-46f0-bb36-53a6053776c8}
+ SystemRuntimeAnalyzers
+
+
+
+
+ False
+ ..\..\..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/packages.config b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/packages.config
new file mode 100644
index 0000000000000..7a5f834c82a3f
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/CSharp/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/CodeFixProviderBase.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/CodeFixProviderBase.cs
new file mode 100644
index 0000000000000..2e914bff0087e
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/CodeFixProviderBase.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+
+namespace System.Runtime.Analyzers
+{
+ public abstract class CodeFixProviderBase : CodeFixProvider
+ {
+ protected abstract string GetCodeFixDescription(Diagnostic diagnostic);
+
+ internal abstract Task GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken);
+
+ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ var document = context.Document;
+ var cancellationToken = context.CancellationToken;
+
+ var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
+ var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
+
+ foreach (var diagnostic in context.Diagnostics)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var nodeToFix = root.FindNode(diagnostic.Location.SourceSpan);
+
+ var newDocument = await GetUpdatedDocumentAsync(document, model, root, nodeToFix, diagnostic, cancellationToken).ConfigureAwait(false);
+
+ Debug.Assert(newDocument != null);
+ if (newDocument != document)
+ {
+ var codeFixDescription = GetCodeFixDescription(diagnostic);
+ context.RegisterCodeFix(new MyCodeAction(codeFixDescription, newDocument), diagnostic);
+ }
+ }
+ }
+
+ private class MyCodeAction : DocumentChangeAction
+ {
+ public MyCodeAction(string title, Document newDocument) :
+ base(title, c => Task.FromResult(newDocument))
+ {
+ }
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.Fixer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.Fixer.cs
new file mode 100644
index 0000000000000..24cf7c5f0331f
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.Fixer.cs
@@ -0,0 +1,85 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Immutable;
+using System.Composition;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.Editing;
+using Microsoft.CodeAnalysis.Formatting;
+
+namespace System.Runtime.Analyzers
+{
+ ///
+ /// CA1001: Types that own disposable fields should be disposable
+ ///
+ [ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic), Shared]
+ public class TypesThatOwnDisposableFieldsShouldBeDisposableFixer : CodeFixProvider
+ {
+ protected const string NotImplementedExceptionName = "System.NotImplementedException";
+ protected const string IDisposableName = "System.IDisposable";
+
+ public sealed override ImmutableArray FixableDiagnosticIds
+ {
+ get { return ImmutableArray.Create(TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer.RuleId); }
+ }
+
+ protected string GetCodeFixDescription(Diagnostic diagnostic)
+ {
+ return SystemRuntimeAnalyzersResources.ImplementIDisposableInterface;
+ }
+
+ public async override Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ var generator = SyntaxGenerator.GetGenerator(context.Document);
+ var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
+
+ var declaration = root.FindNode(context.Span);
+ declaration = generator.GetDeclaration(declaration);
+
+ if (declaration == null)
+ {
+ return;
+ }
+
+ // We cannot have multiple overlapping diagnostics of this id.
+ var diagnostic = context.Diagnostics.Single();
+
+ context.RegisterCodeFix(new DocumentChangeAction(SystemRuntimeAnalyzersResources.ImplementIDisposableInterface,
+ async ct => await ImplementIDisposable(context.Document, declaration, ct).ConfigureAwait(false)),
+ diagnostic);
+ }
+
+ private async Task ImplementIDisposable(Document document, SyntaxNode declaration, CancellationToken cancellationToken)
+ {
+ DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
+ var generator = editor.Generator;
+ var model = editor.SemanticModel;
+
+ // Add the interface to the baselist.
+ var interfaceType = generator.TypeExpression(WellKnownTypes.IDisposable(model.Compilation));
+ editor.AddInterfaceType(declaration, interfaceType);
+
+ // Find a Dispose method. If one exists make that implement IDisposable, else generate a new method.
+ var typeSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
+ var disposeMethod = (typeSymbol?.GetMembers("Dispose"))?.OfType()?.Where(m => m.Parameters.Length == 0).FirstOrDefault();
+ if (disposeMethod != null && disposeMethod.DeclaringSyntaxReferences.Length == 1)
+ {
+ var memberPartNode = await disposeMethod.DeclaringSyntaxReferences.Single().GetSyntaxAsync(cancellationToken).ConfigureAwait(false);
+ memberPartNode = generator.GetDeclaration(memberPartNode);
+ editor.ReplaceNode(memberPartNode, generator.AsPublicInterfaceImplementation(memberPartNode, interfaceType));
+ }
+ else
+ {
+ var throwStatement = generator.ThrowStatement(generator.ObjectCreationExpression(WellKnownTypes.NotImplementedException(model.Compilation)));
+ var member = generator.MethodDeclaration(TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer.Dispose, statements: new[] { throwStatement });
+ member = generator.AsPublicInterfaceImplementation(member, interfaceType);
+ editor.AddMember(declaration, member);
+ }
+
+ return editor.GetChangedDocument();
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/Core/Design/CA1001DiagnosticAnalyzer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.cs
similarity index 65%
rename from src/Diagnostics/FxCop/Core/Design/CA1001DiagnosticAnalyzer.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.cs
index be6c510698e20..0ac28edff1993 100644
--- a/src/Diagnostics/FxCop/Core/Design/CA1001DiagnosticAnalyzer.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/Design/TypesThatOwnDisposableFieldsShouldBeDisposable.cs
@@ -1,34 +1,32 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
-namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
+namespace System.Runtime.Analyzers
{
///
/// CA1001: Types that own disposable fields should be disposable
///
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
- public sealed class CA1001DiagnosticAnalyzer : AbstractNamedTypeAnalyzer
+ public sealed class TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer : DiagnosticAnalyzer
{
internal const string RuleId = "CA1001";
internal const string Dispose = "Dispose";
internal const string IDisposable = "System.IDisposable";
internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId,
- new LocalizableResourceString(nameof(FxCopRulesResources.TypesThatOwnDisposableFieldsShouldBeDisposable), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources)),
- new LocalizableResourceString(nameof(FxCopRulesResources.TypeOwnsDisposableFieldButIsNotDisposable), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources)),
- FxCopDiagnosticCategory.Design,
+ new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.TypesThatOwnDisposableFieldsShouldBeDisposable), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources)),
+ new LocalizableResourceString(nameof(SystemRuntimeAnalyzersResources.TypeOwnsDisposableFieldButIsNotDisposable), SystemRuntimeAnalyzersResources.ResourceManager, typeof(SystemRuntimeAnalyzersResources)),
+ DiagnosticCategory.Design,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: "http://msdn.microsoft.com/library/ms182172.aspx",
- customTags: DiagnosticCustomTags.Microsoft);
+ customTags: WellKnownDiagnosticTags.Telemetry);
public override ImmutableArray SupportedDiagnostics
{
@@ -38,7 +36,16 @@ public override ImmutableArray SupportedDiagnostics
}
}
- protected override void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken)
+ public override void Initialize(AnalysisContext analysisContext)
+ {
+ analysisContext.RegisterSymbolAction(context =>
+ {
+ AnalyzeSymbol((INamedTypeSymbol)context.Symbol, context.Compilation, context.ReportDiagnostic, context.Options, context.CancellationToken);
+ },
+ SymbolKind.NamedType);
+ }
+
+ private static void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken)
{
var disposableType = WellKnownTypes.IDisposable(compilation);
if (disposableType != null && !symbol.AllInterfaces.Contains(disposableType))
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DiagnosticCategory.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DiagnosticCategory.cs
new file mode 100644
index 0000000000000..e67dfb9b94e99
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DiagnosticCategory.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+namespace System.Runtime.Analyzers
+{
+ internal static class DiagnosticCategory
+ {
+ public static readonly string Design = SystemRuntimeAnalyzersResources.CategoryDesign;
+ public static readonly string Globalization = SystemRuntimeAnalyzersResources.CategoryGlobalization;
+ public static readonly string Interoperability = SystemRuntimeAnalyzersResources.CategoryInteroperability;
+ public static readonly string Performance = SystemRuntimeAnalyzersResources.CategoryPerformance;
+ public static readonly string Reliability = SystemRuntimeAnalyzersResources.CategoryReliability;
+ public static readonly string Usage = SystemRuntimeAnalyzersResources.CategoryUsage;
+ public static readonly string Naming = SystemRuntimeAnalyzersResources.CategoryNaming;
+ }
+}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DiagnosticExtensions.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DiagnosticExtensions.cs
new file mode 100644
index 0000000000000..14385329d7868
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DiagnosticExtensions.cs
@@ -0,0 +1,135 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+
+namespace System.Runtime.Analyzers
+{
+ internal static class DiagnosticExtensions
+ {
+ public static IEnumerable CreateDiagnostics(
+ this IEnumerable nodes,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ foreach (var node in nodes)
+ {
+ yield return node.CreateDiagnostic(rule, args);
+ }
+ }
+
+ public static Diagnostic CreateDiagnostic(
+ this SyntaxNode node,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ return node.GetLocation().CreateDiagnostic(rule, args);
+ }
+
+ public static IEnumerable CreateDiagnostics(
+ this IEnumerable tokens,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ foreach (var token in tokens)
+ {
+ yield return token.CreateDiagnostic(rule, args);
+ }
+ }
+
+ public static Diagnostic CreateDiagnostic(
+ this SyntaxToken token,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ return token.GetLocation().CreateDiagnostic(rule, args);
+ }
+
+ public static IEnumerable CreateDiagnostics(
+ this IEnumerable nodesOrTokens,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ foreach (var nodeOrToken in nodesOrTokens)
+ {
+ yield return nodeOrToken.CreateDiagnostic(rule, args);
+ }
+ }
+
+ public static Diagnostic CreateDiagnostic(
+ this SyntaxNodeOrToken nodeOrToken,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ return nodeOrToken.GetLocation().CreateDiagnostic(rule, args);
+ }
+
+ public static IEnumerable CreateDiagnostics(
+ this IEnumerable symbols,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ foreach (var symbol in symbols)
+ {
+ yield return symbol.CreateDiagnostic(rule, args);
+ }
+ }
+
+ public static Diagnostic CreateDiagnostic(
+ this ISymbol symbol,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ return symbol.Locations.CreateDiagnostic(rule, args);
+ }
+
+ public static IEnumerable CreateDiagnostics(
+ this IEnumerable locations,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ foreach (var location in locations)
+ {
+ yield return location.CreateDiagnostic(rule, args);
+ }
+ }
+
+ public static Diagnostic CreateDiagnostic(
+ this Location location,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ if (!location.IsInSource)
+ {
+ return Diagnostic.Create(rule, null, args);
+ }
+
+ return Diagnostic.Create(rule, location, args);
+ }
+
+ public static IEnumerable CreateDiagnostics(
+ this IEnumerable> setOfLocations,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ foreach (var locations in setOfLocations)
+ {
+ yield return locations.CreateDiagnostic(rule, args);
+ }
+ }
+
+ public static Diagnostic CreateDiagnostic(
+ this IEnumerable locations,
+ DiagnosticDescriptor rule,
+ params object[] args)
+ {
+ var location = locations.First(l => l.IsInSource);
+ var additionalLocations = locations.Where(l => l.IsInSource).Skip(1);
+ return Diagnostic.Create(rule,
+ location: location,
+ additionalLocations: additionalLocations,
+ messageArgs: args);
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DocumentChangeAction.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DocumentChangeAction.cs
new file mode 100644
index 0000000000000..903f096b846ee
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/DocumentChangeAction.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeActions;
+
+namespace Microsoft.CodeAnalysis
+{
+ internal class DocumentChangeAction : CodeAction
+ {
+ private readonly string _title;
+ private readonly Func> _createChangedDocument;
+
+ public DocumentChangeAction(string title, Func> createChangedDocument)
+ {
+ _title = title;
+ _createChangedDocument = createChangedDocument;
+ }
+
+ public override string Title
+ {
+ get { return _title; }
+ }
+
+ protected override Task GetChangedDocumentAsync(CancellationToken cancellationToken)
+ {
+ return _createChangedDocument(cancellationToken);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj
new file mode 100644
index 0000000000000..18d0809a953fe
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzers.csproj
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+ 12.0
+ Debug
+ AnyCPU
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8}
+ Library
+ true
+ System.Runtime.Analyzers
+ System.Runtime.Analyzers
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Profile7
+ .NETPortable
+ true
+
+
+
+
+
+
+
+
+ {1ee8cad3-55f9-4d91-96b2-084641da9a6c}
+ CodeAnalysis
+
+
+ {5f8d2414-064a-4b3a-9b42-8e2a04246be5}
+ Workspaces
+
+
+
+
+ False
+ ..\..\..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ SystemRuntimeAnalyzersResources.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ SystemRuntimeAnalyzersResources.Designer.cs
+
+
+
+
+
+
+
+
+
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs
new file mode 100644
index 0000000000000..b0f895fa2f7d9
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.Designer.cs
@@ -0,0 +1,154 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.0
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace System.Runtime.Analyzers {
+ using System;
+ using System.Reflection;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class SystemRuntimeAnalyzersResources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal SystemRuntimeAnalyzersResources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Runtime.Analyzers.SystemRuntimeAnalyzersResources", typeof(SystemRuntimeAnalyzersResources).GetTypeInfo().Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Design.
+ ///
+ internal static string CategoryDesign {
+ get {
+ return ResourceManager.GetString("CategoryDesign", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Globalization.
+ ///
+ internal static string CategoryGlobalization {
+ get {
+ return ResourceManager.GetString("CategoryGlobalization", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Interoperability.
+ ///
+ internal static string CategoryInteroperability {
+ get {
+ return ResourceManager.GetString("CategoryInteroperability", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Naming.
+ ///
+ internal static string CategoryNaming {
+ get {
+ return ResourceManager.GetString("CategoryNaming", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Performance.
+ ///
+ internal static string CategoryPerformance {
+ get {
+ return ResourceManager.GetString("CategoryPerformance", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Reliability.
+ ///
+ internal static string CategoryReliability {
+ get {
+ return ResourceManager.GetString("CategoryReliability", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Usage.
+ ///
+ internal static string CategoryUsage {
+ get {
+ return ResourceManager.GetString("CategoryUsage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Implement IDisposable Interface.
+ ///
+ internal static string ImplementIDisposableInterface {
+ get {
+ return ResourceManager.GetString("ImplementIDisposableInterface", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Type '{0}' owns disposable fields but is not disposable.
+ ///
+ internal static string TypeOwnsDisposableFieldButIsNotDisposable {
+ get {
+ return ResourceManager.GetString("TypeOwnsDisposableFieldButIsNotDisposable", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Types that own disposable fields should be disposable.
+ ///
+ internal static string TypesThatOwnDisposableFieldsShouldBeDisposable {
+ get {
+ return ResourceManager.GetString("TypesThatOwnDisposableFieldsShouldBeDisposable", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx
new file mode 100644
index 0000000000000..ceac435cd70bf
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/SystemRuntimeAnalyzersResources.resx
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Types that own disposable fields should be disposable
+
+
+ Design
+
+
+ Globalization
+
+
+ Interoperability
+
+
+ Naming
+
+
+ Performance
+
+
+ Reliability
+
+
+ Usage
+
+
+ Implement IDisposable Interface
+
+
+ Type '{0}' owns disposable fields but is not disposable
+
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/WellKnownTypes.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/WellKnownTypes.cs
new file mode 100644
index 0000000000000..5676c11a1af43
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/WellKnownTypes.cs
@@ -0,0 +1,174 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.CodeAnalysis;
+
+namespace System.Runtime.Analyzers
+{
+ internal static class WellKnownTypes
+ {
+ public static INamedTypeSymbol FlagsAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.FlagsAttribute");
+ }
+
+ public static INamedTypeSymbol StringComparison(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.StringComparison");
+ }
+
+ public static INamedTypeSymbol CharSet(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.InteropServices.CharSet");
+ }
+
+ public static INamedTypeSymbol DllImportAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.InteropServices.DllImportAttribute");
+ }
+
+ public static INamedTypeSymbol MarshalAsAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.InteropServices.MarshalAsAttribute");
+ }
+
+ public static INamedTypeSymbol StringBuilder(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Text.StringBuilder");
+ }
+
+ public static INamedTypeSymbol UnmanagedType(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedType");
+ }
+
+ public static INamedTypeSymbol MarshalByRefObject(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.MarshalByRefObject");
+ }
+
+ public static INamedTypeSymbol ExecutionEngineException(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.ExecutionEngineException");
+ }
+
+ public static INamedTypeSymbol OutOfMemoryException(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.OutOfMemoryException");
+ }
+
+ public static INamedTypeSymbol StackOverflowException(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.StackOverflowException");
+ }
+
+ public static INamedTypeSymbol MemberInfo(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Reflection.MemberInfo");
+ }
+
+ public static INamedTypeSymbol ParameterInfo(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Reflection.ParameterInfo");
+ }
+
+ public static INamedTypeSymbol Thread(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Threading.Thread");
+ }
+
+ public static INamedTypeSymbol WebUIControl(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Web.UI.Control");
+ }
+
+ public static INamedTypeSymbol WinFormsUIControl(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Windows.Forms.Control");
+ }
+
+ public static INamedTypeSymbol IDisposable(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.IDisposable");
+ }
+
+ public static INamedTypeSymbol ISerializable(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.Serialization.ISerializable");
+ }
+
+ public static INamedTypeSymbol SerializationInfo(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.Serialization.SerializationInfo");
+ }
+
+ public static INamedTypeSymbol StreamingContext(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.Serialization.StreamingContext");
+ }
+
+ public static INamedTypeSymbol SerializableAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.SerializableAttribute");
+ }
+
+ public static INamedTypeSymbol NonSerializedAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.NonSerializedAttribute");
+ }
+
+ public static INamedTypeSymbol AttributeUsageAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.AttributeUsageAttribute");
+ }
+
+ public static INamedTypeSymbol AssemblyVersionAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Reflection.AssemblyVersionAttribute");
+ }
+
+ public static INamedTypeSymbol CLSCompliantAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.CLSCompliantAttribute");
+ }
+
+ public static INamedTypeSymbol ConditionalAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Diagnostics.ConditionalAttribute");
+ }
+
+ public static INamedTypeSymbol IComparable(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.IComparable");
+ }
+
+ public static INamedTypeSymbol ComSourceInterfaceAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.InteropServices.ComSourceInterfacesAttribute");
+ }
+
+ public static INamedTypeSymbol EventHandler(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.EventHandler");
+ }
+
+ public static INamedTypeSymbol GenericEventHandler(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.EventHandler`1");
+ }
+
+ public static INamedTypeSymbol EventArgs(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.EventArgs");
+ }
+
+ public static INamedTypeSymbol ComVisibleAttribute(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.Runtime.InteropServices.ComVisibleAttribute");
+ }
+
+ public static INamedTypeSymbol NotImplementedException(Compilation compilation)
+ {
+ return compilation.GetTypeByMetadataName("System.NotImplementedException");
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/packages.config b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/packages.config
new file mode 100644
index 0000000000000..7a5f834c82a3f
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Core/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj
new file mode 100644
index 0000000000000..8fcaccde7c94f
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/SystemRuntimeAnalyzersTest.csproj
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+ Debug
+ AnyCPU
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}
+ Library
+ System.Runtime.Analyzers.UnitTests
+ System.Runtime.Analyzers.UnitTests
+ true
+ ..\..\..\..\
+ true
+
+
+
+ {dfa21ca1-7f96-47ee-940c-069858e81727}
+ CodeAnalysis.Desktop
+
+
+ {1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}
+ CodeAnalysis
+
+
+ {B501A547-C911-4A05-AC6E-274A50DFF30E}
+ CSharpCodeAnalysis
+
+
+ {73f3e2c5-d742-452e-b9e1-20732ddbc75d}
+ BasicCodeAnalysis.Desktop
+
+
+ {2523D0E6-DF32-4A3E-8AE0-A19BFFAE2EF6}
+ BasicCodeAnalysis
+
+
+ {76C6F005-C89D-4348-BB4A-391898DBEB52}
+ TestUtilities
+
+
+ {21B239D0-D144-430F-A394-C066D58EE267}
+ CSharpWorkspace
+
+
+ {57CA988D-F010-4BF2-9A2E-07D6DCD2FF2C}
+ BasicWorkspace
+
+
+ {5F8D2414-064A-4B3A-9B42-8E2A04246BE5}
+ Workspaces
+
+
+ {0A0621F2-D1DC-47FF-B643-C6646557505E}
+ DiagnosticsTestUtilities
+
+
+ {7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}
+ CompilerTestResources
+ false
+
+
+ {baa0fee4-93c8-46f0-bb36-53a6053776c8}
+ SystemRuntimeAnalyzers
+
+
+ {a36451ec-1127-40ce-b841-47f393d24624}
+ CSharpSystemRuntimeAnalyzers
+
+
+ {d835c05e-9d83-40b2-9d25-19eb652f10d7}
+ BasicSystemRuntimeAnalyzers
+
+
+
+
+
+
+
+
+
+ False
+ ..\..\..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ ..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/TypesThatOwnDisposableFieldsShouldBeDisposableTests.Fixer.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/TypesThatOwnDisposableFieldsShouldBeDisposableTests.Fixer.cs
new file mode 100644
index 0000000000000..eccb7c9f1df34
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/TypesThatOwnDisposableFieldsShouldBeDisposableTests.Fixer.cs
@@ -0,0 +1,256 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.CodeAnalysis.UnitTests;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace System.Runtime.Analyzers.UnitTests
+{
+ public partial class CA1001FixerTests : CodeFixTestBase
+ {
+ protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
+ {
+ return new TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer();
+ }
+
+ protected override CodeFixProvider GetBasicCodeFixProvider()
+ {
+ return new TypesThatOwnDisposableFieldsShouldBeDisposableFixer();
+ }
+
+ protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
+ {
+ return new TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer();
+ }
+
+ protected override CodeFixProvider GetCSharpCodeFixProvider()
+ {
+ return new TypesThatOwnDisposableFieldsShouldBeDisposableFixer();
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
+ public void CA1001CSharpCodeFixNoDispose()
+ {
+ VerifyCSharpFix(@"
+using System;
+using System.IO;
+
+// This class violates the rule.
+public class NoDisposeClass
+{
+ FileStream newFile;
+
+ public NoDisposeClass()
+ {
+ newFile = new FileStream("""", FileMode.Append);
+ }
+}
+",
+@"
+using System;
+using System.IO;
+
+// This class violates the rule.
+public class NoDisposeClass
+: IDisposable
+{
+ FileStream newFile;
+
+ public NoDisposeClass()
+ {
+ newFile = new FileStream("""", FileMode.Append);
+ }
+
+ public void Dispose()
+ {
+ throw new NotImplementedException();
+ }
+}
+");
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
+ public void CA1001BasicCodeFixNoDispose()
+ {
+ VerifyBasicFix(@"
+Imports System
+Imports System.IO
+
+' This class violates the rule.
+Public Class NoDisposeMethod
+
+ Dim newFile As FileStream
+
+ Sub New()
+ newFile = New FileStream("""", FileMode.Append)
+ End Sub
+
+End Class
+",
+@"
+Imports System
+Imports System.IO
+
+' This class violates the rule.
+Public Class NoDisposeMethod
+ Implements IDisposable
+
+ Dim newFile As FileStream
+
+ Sub New()
+ newFile = New FileStream("""", FileMode.Append)
+ End Sub
+
+ Sub Dispose() Implements IDisposable.Dispose
+ Throw New NotImplementedException()
+ End Sub
+End Class
+");
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
+ public void CA1001CSharpCodeFixHasDispose()
+ {
+ VerifyCSharpFix(@"
+using System;
+using System.IO;
+
+// This class violates the rule.
+public class NoDisposeClass
+{
+ FileStream newFile;
+
+ void Dispose() {
+// Some content
+}
+}
+",
+@"
+using System;
+using System.IO;
+
+// This class violates the rule.
+public class NoDisposeClass
+: IDisposable
+{
+ FileStream newFile;
+
+ public void Dispose() {
+// Some content
+}
+}
+");
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
+ public void CA1001CSharpCodeFixHasWrongDispose()
+ {
+ VerifyCSharpFix(@"
+using System;
+using System.IO;
+
+// This class violates the rule.
+public partial class NoDisposeClass
+{
+ FileStream newFile;
+
+ void Dispose(int x) {
+// Some content
+}
+}
+",
+@"
+using System;
+using System.IO;
+
+// This class violates the rule.
+public partial class NoDisposeClass
+: IDisposable
+{
+ FileStream newFile;
+
+ void Dispose(int x) {
+// Some content
+}
+
+ public void Dispose()
+ {
+ throw new NotImplementedException();
+ }
+}
+");
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
+ public void CA1001BasicCodeFixHasDispose()
+ {
+ VerifyBasicFix(@"
+Imports System
+Imports System.IO
+
+' This class violates the rule.
+Public Class NoDisposeMethod
+
+ Dim newFile As FileStream
+
+ Sub Dispose()
+
+ End Sub
+End Class
+",
+@"
+Imports System
+Imports System.IO
+
+' This class violates the rule.
+Public Class NoDisposeMethod
+ Implements IDisposable
+
+ Dim newFile As FileStream
+
+ Sub Dispose() Implements IDisposable.Dispose
+ End Sub
+End Class
+");
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
+ public void CA1001BasicCodeFixHasWrongDispose()
+ {
+ VerifyBasicFix(@"
+Imports System
+Imports System.IO
+
+' This class violates the rule.
+Public Class NoDisposeMethod
+
+ Dim newFile As FileStream
+
+ Sub Dispose(x As Integer)
+ End Sub
+End Class
+",
+@"
+Imports System
+Imports System.IO
+
+' This class violates the rule.
+Public Class NoDisposeMethod
+ Implements IDisposable
+
+ Dim newFile As FileStream
+
+ Sub Dispose(x As Integer)
+ End Sub
+
+ Sub Dispose() Implements IDisposable.Dispose
+ Throw New NotImplementedException()
+ End Sub
+End Class
+");
+ }
+ }
+}
diff --git a/src/Diagnostics/FxCop/Test/Design/CA1001Tests.cs b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/TypesThatOwnDisposableFieldsShouldBeDisposableTests.cs
similarity index 96%
rename from src/Diagnostics/FxCop/Test/Design/CA1001Tests.cs
rename to src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/TypesThatOwnDisposableFieldsShouldBeDisposableTests.cs
index 611f9f82aa54b..540ca3d31fc44 100644
--- a/src/Diagnostics/FxCop/Test/Design/CA1001Tests.cs
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/TypesThatOwnDisposableFieldsShouldBeDisposableTests.cs
@@ -1,22 +1,22 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Design;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
-namespace Microsoft.CodeAnalysis.UnitTests
+namespace System.Runtime.Analyzers.UnitTests
{
public partial class CA1001Tests : DiagnosticAnalyzerTestBase
{
protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
{
- return new CA1001DiagnosticAnalyzer();
+ return new TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer();
}
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
{
- return new CA1001DiagnosticAnalyzer();
+ return new TypesThatOwnDisposableFieldsShouldBeDisposableAnalyzer();
}
[Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/packages.config b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/packages.config
new file mode 100644
index 0000000000000..a972616f20fdd
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/Test/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/BasicSystemRuntimeAnalyzers.vbproj b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/BasicSystemRuntimeAnalyzers.vbproj
new file mode 100644
index 0000000000000..ede2e04d6cee0
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/BasicSystemRuntimeAnalyzers.vbproj
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+ 12.0
+ Debug
+ AnyCPU
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7}
+ Library
+ true
+ Microsoft.CodeAnalysis.VisualBasic.Analyzers
+ {14182A97-F7F0-4C62-8B27-98AA8AE2109A};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}
+ Profile7
+ .NETPortable
+ true
+
+
+
+
+
+
+
+
+ {1ee8cad3-55f9-4d91-96b2-084641da9a6c}
+ CodeAnalysis
+
+
+ {2523d0e6-df32-4a3e-8ae0-a19bffae2ef6}
+ BasicCodeAnalysis
+
+
+ {5f8d2414-064a-4b3a-9b42-8e2a04246be5}
+ Workspaces
+
+
+ {d8762a0a-3832-47be-bcf6-8b1060be6b28}
+ CodeAnalysisDiagnosticAnalyzers
+
+
+
+
+ False
+ ..\..\..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll
+
+
+ False
+ ..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/packages.config b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/packages.config
new file mode 100644
index 0000000000000..7a5f834c82a3f
--- /dev/null
+++ b/src/Diagnostics/FxCop/System.Runtime.Analyzers/VisualBasic/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/Diagnostics/FxCop/Test/Design/CodeFixes/CA1001FixerTests.cs b/src/Diagnostics/FxCop/Test/Design/CodeFixes/CA1001FixerTests.cs
deleted file mode 100644
index 8cc96629caea9..0000000000000
--- a/src/Diagnostics/FxCop/Test/Design/CodeFixes/CA1001FixerTests.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using Microsoft.CodeAnalysis.CodeFixes;
-using Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers.Design;
-using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.CodeAnalysis.FxCopAnalyzers.Design;
-using Microsoft.CodeAnalysis.Test.Utilities;
-using Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Design;
-using Xunit;
-
-namespace Microsoft.CodeAnalysis.UnitTests
-{
- public partial class CA1001FixerTests : CodeFixTestBase
- {
- protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
- {
- return new CA1001DiagnosticAnalyzer();
- }
-
- protected override CodeFixProvider GetBasicCodeFixProvider()
- {
- return new CA1001BasicCodeFixProvider();
- }
-
- protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
- {
- return new CA1001DiagnosticAnalyzer();
- }
-
- protected override CodeFixProvider GetCSharpCodeFixProvider()
- {
- return new CA1001CSharpCodeFixProvider();
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
- public void CA1001CSharpCodeFixNoEqualsOperator()
- {
- VerifyCSharpFix(@"
-using System;
-using System.IO;
-
-// This class violates the rule.
-public class NoDisposeClass
-{
- FileStream newFile;
-
- public NoDisposeClass()
- {
- newFile = new FileStream("""", FileMode.Append);
- }
-}
-",
-@"
-using System;
-using System.IO;
-
-// This class violates the rule.
-public class NoDisposeClass : IDisposable
-{
- FileStream newFile;
-
- public NoDisposeClass()
- {
- newFile = new FileStream("""", FileMode.Append);
- }
-
- public void Dispose()
- {
- throw new NotImplementedException();
- }
-}
-");
- }
-
- [Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
- public void CA1001BasicCodeFixNoEqualsOperator()
- {
- VerifyBasicFix(@"
-Imports System
-Imports System.IO
-
-' This class violates the rule.
-Public Class NoDisposeMethod
-
- Dim newFile As FileStream
-
- Sub New()
- newFile = New FileStream("""", FileMode.Append)
- End Sub
-
-End Class
-",
-@"
-Imports System
-Imports System.IO
-
-' This class violates the rule.
-Public Class NoDisposeMethod
- Implements IDisposable
-
- Dim newFile As FileStream
-
- Sub New()
- newFile = New FileStream("""", FileMode.Append)
- End Sub
-
- Public Sub Dispose() Implements IDisposable.Dispose
- Throw New NotImplementedException()
- End Sub
-End Class
-");
- }
- }
-}
diff --git a/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj b/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj
index 60d2af1789593..5e4f45f6d0694 100644
--- a/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj
+++ b/src/Diagnostics/FxCop/Test/FxCopRulesDiagnosticAnalyzersTest.csproj
@@ -80,7 +80,6 @@
-
@@ -93,7 +92,6 @@
-
@@ -150,4 +148,4 @@
-
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj b/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj
index 13959b07250cb..90c94cb6f9b52 100644
--- a/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj
+++ b/src/Diagnostics/FxCop/VisualBasic/BasicFxCopRulesDiagnosticAnalyzers.vbproj
@@ -99,7 +99,6 @@
-
@@ -132,4 +131,4 @@
-
+
\ No newline at end of file
diff --git a/src/Diagnostics/FxCop/VisualBasic/Design/CodeFixes/CA1001BasicCodeFixProvider.vb b/src/Diagnostics/FxCop/VisualBasic/Design/CodeFixes/CA1001BasicCodeFixProvider.vb
deleted file mode 100644
index 3a07a99fea72d..0000000000000
--- a/src/Diagnostics/FxCop/VisualBasic/Design/CodeFixes/CA1001BasicCodeFixProvider.vb
+++ /dev/null
@@ -1,82 +0,0 @@
-' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-Imports System.Composition
-Imports System.Threading
-Imports Microsoft.CodeAnalysis
-Imports Microsoft.CodeAnalysis.CodeFixes
-Imports Microsoft.CodeAnalysis.Formatting
-Imports Microsoft.CodeAnalysis.FxCopAnalyzers.Design
-Imports Microsoft.CodeAnalysis.Simplification
-Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
-
-Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Design
- '
- ' CA1001: Types that own disposable fields should be disposable
- '
-
- Public Class CA1001BasicCodeFixProvider
- Inherits CA1001CodeFixProviderBase
-
- Friend Overrides Function GetUpdatedDocumentAsync(document As Document, model As SemanticModel, root As SyntaxNode, nodeToFix As SyntaxNode, diagnostic As Diagnostic, cancellationToken As CancellationToken) As Task(Of Document)
- ' We are going to implement IDisposable interface
- '
- ' Public Sub Dispose() Implements IDisposable.Dispose
- ' Throw New NotImplementedException()
- ' End Sub
-
- Dim syntaxNode = TryCast(nodeToFix, ClassStatementSyntax)
- If syntaxNode Is Nothing Then
- Return Task.FromResult(document)
- End If
-
- Dim statement = CreateThrowNotImplementedStatement(model)
- If statement Is Nothing Then
- Return Task.FromResult(document)
- End If
-
- Dim member = CreateSimpleSubBlockDeclaration(CA1001DiagnosticAnalyzer.Dispose, statement)
- Dim parent = DirectCast(syntaxNode.Parent, ClassBlockSyntax)
- Dim implementsStatement = SyntaxFactory.ImplementsStatement(
- SyntaxFactory.ParseTypeName(CA1001DiagnosticAnalyzer.IDisposable) _
- .WithAdditionalAnnotations(Simplifier.Annotation)) _
- .WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed)
-
- Dim newNode = parent.AddMembers(New MethodBlockSyntax() {member}).AddImplements(implementsStatement).WithAdditionalAnnotations(Formatter.Annotation)
- Return Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode(parent, newNode)))
- End Function
-
- Protected Function CreateThrowNotImplementedStatement(model As SemanticModel) As StatementSyntax
- Dim exceptionType = model.Compilation.GetTypeByMetadataName(NotImplementedExceptionName)
- If exceptionType Is Nothing Then
- ' If we can't find the exception, we can't generate anything.
- Return Nothing
- End If
-
- Return SyntaxFactory.ThrowStatement(
- SyntaxFactory.ObjectCreationExpression(
- Nothing,
- SyntaxFactory.ParseTypeName(exceptionType.Name),
- SyntaxFactory.ArgumentList(),
- Nothing))
- End Function
-
- Protected Function CreateSimpleSubBlockDeclaration(name As String, statement As StatementSyntax) As MethodBlockSyntax
- Return SyntaxFactory.SubBlock(
- SyntaxFactory.SubStatement(
- Nothing,
- SyntaxFactory.TokenList(New SyntaxToken() {SyntaxFactory.Token(SyntaxKind.PublicKeyword)}),
- SyntaxFactory.Token(SyntaxKind.SubKeyword),
- SyntaxFactory.Identifier(name),
- Nothing,
- SyntaxFactory.ParameterList(),
- Nothing,
- Nothing,
- SyntaxFactory.ImplementsClause(
- SyntaxFactory.QualifiedName(
- SyntaxFactory.ParseName(CA1001DiagnosticAnalyzer.IDisposable),
- SyntaxFactory.IdentifierName(CA1001DiagnosticAnalyzer.Dispose)) _
- .WithAdditionalAnnotations(Simplifier.Annotation))),
- SyntaxFactory.SingletonList(statement))
- End Function
- End Class
-End Namespace
diff --git a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
index 031328a063af5..8c32d4ce8aa82 100644
--- a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
+++ b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
@@ -224,6 +224,7 @@
+
@@ -614,10 +615,7 @@
PreserveNewest
-
-
-
-
+
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/FixAllProvider/BatchFixerTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/FixAllProvider/BatchFixerTests.cs
new file mode 100644
index 0000000000000..0ad40aa333f6e
--- /dev/null
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/FixAllProvider/BatchFixerTests.cs
@@ -0,0 +1,160 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Immutable;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.SimplifyTypeNames
+{
+ public partial class BatchFixerTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
+ {
+ internal override Tuple CreateDiagnosticProviderAndFixer(Workspace workspace)
+ {
+ return Tuple.Create(new QualifyWithThisAnalyzer(), new QualifyWithThisFixer());
+ }
+
+ [DiagnosticAnalyzer(LanguageNames.CSharp)]
+ private class QualifyWithThisAnalyzer : DiagnosticAnalyzer
+ {
+ public static readonly DiagnosticDescriptor Descriptor = new TriggerDiagnosticDescriptor("QualifyWithThis");
+
+ public override ImmutableArray SupportedDiagnostics
+ {
+ get
+ {
+ return ImmutableArray.Create(Descriptor);
+ }
+ }
+
+ public override void Initialize(AnalysisContext context)
+ {
+ context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.IdentifierName);
+ }
+
+ private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
+ {
+ var node = context.Node as SimpleNameSyntax;
+ if (node != null)
+ {
+ var symbol = context.SemanticModel.GetSymbolInfo(node).Symbol;
+ if (symbol != null && symbol.Kind == SymbolKind.Field)
+ {
+ var diagnostic = Diagnostic.Create(Descriptor, node.GetLocation());
+ context.ReportDiagnostic(diagnostic);
+ }
+ }
+ }
+ }
+
+ private class QualifyWithThisFixer : CodeFixProvider
+ {
+ public override ImmutableArray FixableDiagnosticIds
+ {
+ get
+ {
+ return ImmutableArray.Create(QualifyWithThisAnalyzer.Descriptor.Id);
+ }
+ }
+
+ public async override Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
+ var node = root.FindNode(context.Span, getInnermostNodeForTie: true) as SimpleNameSyntax;
+ if (node != null)
+ {
+ var leadingTrivia = node.GetLeadingTrivia();
+ var newNode = SyntaxFactory.MemberAccessExpression(
+ SyntaxKind.SimpleMemberAccessExpression,
+ SyntaxFactory.ThisExpression(),
+ node.WithoutLeadingTrivia())
+ .WithLeadingTrivia(leadingTrivia);
+
+ var newRoot = root.ReplaceNode(node, newNode);
+ var newDocument = context.Document.WithSyntaxRoot(newRoot);
+
+ // Disable RS0005 as this is test code and we don't need telemtry for created code action.
+#pragma warning disable RS0005 // Do not use generic CodeAction.Create to create CodeAction
+ var fix = CodeAction.Create("QualifyWithThisFix", _ => Task.FromResult(newDocument));
+#pragma warning restore RS0005 // Do not use generic CodeAction.Create to create CodeAction
+
+ context.RegisterCodeFix(fix, context.Diagnostics);
+ }
+ }
+
+ public override FixAllProvider GetFixAllProvider()
+ {
+ return WellKnownFixAllProviders.BatchFixer;
+ }
+ }
+
+ #region "Fix all occurrences tests"
+
+ [Fact(Skip = "https://github.com/dotnet/roslyn/issues/320")]
+ [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)]
+ public void TestFixAllInDocument_QualifyWithThis()
+ {
+ var input = @"
+
+
+
+class C
+{
+ int Sign;
+ void F()
+ {
+ string x = @""namespace Namespace
+ {
+ class Type
+ {
+ void Foo()
+ {
+ int x = 1 "" + {|FixAllInDocument:Sign|} + @"" "" + Sign + @""3;
+ }
+ }
+ }
+"";
+ }
+}
+
+
+";
+
+ var expected = @"
+
+
+
+class C
+{
+ int Sign;
+ void F()
+ {
+ string x = @""namespace Namespace
+ {
+ class Type
+ {
+ void Foo()
+ {
+ int x = 1 "" + this.Sign + @"" "" + this.Sign + @""3;
+ }
+ }
+ }
+"";
+ }
+}
+
+
+";
+
+ Test(input, expected, isLine: false, compareTokens: false);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/EditorFeatures/Core/Extensibility/Navigation/NavigableItemFactory.DeclaredSymbolNavigableItem.cs b/src/EditorFeatures/Core/Extensibility/Navigation/NavigableItemFactory.DeclaredSymbolNavigableItem.cs
index d03e168d4ce7b..d2654499db228 100644
--- a/src/EditorFeatures/Core/Extensibility/Navigation/NavigableItemFactory.DeclaredSymbolNavigableItem.cs
+++ b/src/EditorFeatures/Core/Extensibility/Navigation/NavigableItemFactory.DeclaredSymbolNavigableItem.cs
@@ -2,10 +2,12 @@
using System;
using System.Threading;
+using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Navigation
{
@@ -33,24 +35,31 @@ public DeclaredSymbolNavigableItem(Document document, DeclaredSymbolInfo declare
_lazySymbol = new Lazy(() => declaredSymbolInfo.GetSymbolAsync(document, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult());
_lazyDisplayName = new Lazy(() =>
{
- if (Symbol == null)
+ try
{
- return null;
- }
+ if (Symbol == null)
+ {
+ return null;
+ }
- var symbolDisplayService = Document.GetLanguageService();
- switch (Symbol.Kind)
- {
- case SymbolKind.NamedType:
- return symbolDisplayService.ToDisplayString(Symbol, s_shortFormatWithModifiers);
+ var symbolDisplayService = Document.GetLanguageService();
+ switch (Symbol.Kind)
+ {
+ case SymbolKind.NamedType:
+ return symbolDisplayService.ToDisplayString(Symbol, s_shortFormatWithModifiers);
- case SymbolKind.Method:
- return Symbol.IsStaticConstructor()
- ? symbolDisplayService.ToDisplayString(Symbol, s_shortFormatWithModifiers)
- : symbolDisplayService.ToDisplayString(Symbol, s_shortFormat);
+ case SymbolKind.Method:
+ return Symbol.IsStaticConstructor()
+ ? symbolDisplayService.ToDisplayString(Symbol, s_shortFormatWithModifiers)
+ : symbolDisplayService.ToDisplayString(Symbol, s_shortFormat);
- default:
- return symbolDisplayService.ToDisplayString(Symbol, s_shortFormat);
+ default:
+ return symbolDisplayService.ToDisplayString(Symbol, s_shortFormat);
+ }
+ }
+ catch (Exception e) when (FatalError.Report(e))
+ {
+ throw ExceptionUtilities.Unreachable;
}
});
}
diff --git a/src/EditorFeatures/VisualBasicTest/NavigateTo/NavigateToTests.vb b/src/EditorFeatures/VisualBasicTest/NavigateTo/NavigateToTests.vb
index 346cd2bf81b4d..a9f4090df4e04 100644
--- a/src/EditorFeatures/VisualBasicTest/NavigateTo/NavigateToTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/NavigateTo/NavigateToTests.vb
@@ -541,6 +541,16 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.NavigateTo
End Using
End Sub
+
+
+ Public Sub FindClassInGlobalNamespace()
+ Using worker = SetupWorkspace("Namespace Global", "Public Class C(Of T)", "End Class", "End Namespace")
+ SetupVerifableGlyph(StandardGlyphGroup.GlyphGroupClass, StandardGlyphItem.GlyphItemPublic)
+ Dim item = _aggregator.GetItems("C").Single
+ VerifyNavigateToResultItem(item, "C", MatchKind.Exact, NavigateToItemKind.Class, displayName:="C(Of T)")
+ End Using
+ End Sub
+
Public Sub StartStopSanity()
' Verify that mutliple calls to start/stop don't blow up
diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpExpressionCompiler.csproj b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpExpressionCompiler.csproj
index a9441ba967cfd..947e1e38ce24c 100644
--- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpExpressionCompiler.csproj
+++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpExpressionCompiler.csproj
@@ -79,6 +79,7 @@
+
diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpFrameDecoder.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpFrameDecoder.cs
index 11fa7caa89349..63ffdb55f5eb3 100644
--- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpFrameDecoder.cs
+++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpFrameDecoder.cs
@@ -1,12 +1,15 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Diagnostics;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
[DkmReportNonFatalWatsonException(ExcludeExceptionType = typeof(NotImplementedException)), DkmContinueCorruptingException]
- internal sealed class CSharpFrameDecoder : FrameDecoder
+ internal sealed class CSharpFrameDecoder : FrameDecoder
{
public CSharpFrameDecoder()
: base(CSharpInstructionDecoder.Instance)
diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpInstructionDecoder.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpInstructionDecoder.cs
index 0c155cc3954c9..772ecc5898a15 100644
--- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpInstructionDecoder.cs
+++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpInstructionDecoder.cs
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System.Diagnostics;
+using System.Collections.Immutable;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
@@ -9,7 +11,7 @@
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
- internal sealed class CSharpInstructionDecoder : InstructionDecoder
+ internal sealed class CSharpInstructionDecoder : InstructionDecoder
{
// This string was not localized in the old EE. We'll keep it that way
// so as not to break consumers who may have been parsing frame names...
@@ -28,7 +30,7 @@ private CSharpInstructionDecoder()
AddMemberOptions(SymbolDisplayMemberOptions.IncludeParameters).
WithParameterOptions(SymbolDisplayParameterOptions.IncludeType);
- internal override void AppendFullName(StringBuilder builder, PEMethodSymbol method)
+ internal override void AppendFullName(StringBuilder builder, MethodSymbol method)
{
var displayFormat =
((method.MethodKind == MethodKind.PropertyGet) || (method.MethodKind == MethodKind.PropertySet)) ?
@@ -86,7 +88,28 @@ internal override void AppendFullName(StringBuilder builder, PEMethodSymbol meth
}
}
- internal override PEMethodSymbol GetMethod(DkmClrInstructionAddress instructionAddress)
+ internal override MethodSymbol ConstructMethod(MethodSymbol method, ImmutableArray typeParameters, ImmutableArray typeArguments)
+ {
+ var methodArity = method.Arity;
+ var methodArgumentStartIndex = typeParameters.Length - methodArity;
+ var typeMap = new TypeMap(
+ ImmutableArray.Create(typeParameters, 0, methodArgumentStartIndex),
+ ImmutableArray.Create(typeArguments, 0, methodArgumentStartIndex));
+ var substitutedType = typeMap.SubstituteNamedType(method.ContainingType);
+ method = method.AsMember(substitutedType);
+ if (methodArity > 0)
+ {
+ method = method.Construct(ImmutableArray.Create(typeArguments, methodArgumentStartIndex, methodArity));
+ }
+ return method;
+ }
+
+ internal override ImmutableArray GetAllTypeParameters(MethodSymbol method)
+ {
+ return method.GetAllTypeParameters();
+ }
+
+ internal override CSharpCompilation GetCompilation(DkmClrInstructionAddress instructionAddress)
{
var moduleInstance = instructionAddress.ModuleInstance;
var appDomain = moduleInstance.AppDomain;
@@ -105,7 +128,18 @@ internal override PEMethodSymbol GetMethod(DkmClrInstructionAddress instructionA
compilation = dataItem.Compilation;
}
- return compilation.GetSourceMethod(moduleInstance.Mvid, instructionAddress.MethodId.Token);
+ return compilation;
+ }
+
+ internal override MethodSymbol GetMethod(CSharpCompilation compilation, DkmClrInstructionAddress instructionAddress)
+ {
+ return compilation.GetSourceMethod(instructionAddress.ModuleInstance.Mvid, instructionAddress.MethodId.Token);
+ }
+
+ internal override TypeNameDecoder GetTypeNameDecoder(CSharpCompilation compilation, MethodSymbol method)
+ {
+ Debug.Assert(method is PEMethodSymbol);
+ return new EETypeNameDecoder(compilation, (PEModuleSymbol)method.ContainingModule);
}
}
}
diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpLanguageInstructionDecoder.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpLanguageInstructionDecoder.cs
index f068b0364d1cf..5787513d95ebc 100644
--- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpLanguageInstructionDecoder.cs
+++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpLanguageInstructionDecoder.cs
@@ -2,16 +2,17 @@
using System;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
[DkmReportNonFatalWatsonException(ExcludeExceptionType = typeof(NotImplementedException)), DkmContinueCorruptingException]
- internal sealed class CSharpLanguageInstructionDecoder : LanguageInstructionDecoder
+ internal sealed class CSharpLanguageInstructionDecoder : LanguageInstructionDecoder
{
public CSharpLanguageInstructionDecoder()
: base(CSharpInstructionDecoder.Instance)
{
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CompilationContext.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CompilationContext.cs
index 4fd8220a4b1c4..a1854491f8e05 100644
--- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CompilationContext.cs
+++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CompilationContext.cs
@@ -245,14 +245,6 @@ internal CommonPEModuleBuilder CompileAssignment(
return module;
}
- private static ImmutableArray GetAllTypeParameters(MethodSymbol method)
- {
- var builder = ArrayBuilder.GetInstance();
- method.ContainingType.GetAllTypeParameters(builder);
- builder.AddRange(method.TypeParameters);
- return builder.ToImmutableAndFree();
- }
-
private static string GetNextMethodName(ArrayBuilder builder)
{
return string.Format("<>m{0}", builder.Count);
@@ -270,7 +262,7 @@ internal CommonPEModuleBuilder CompileGetLocals(
DiagnosticBag diagnostics)
{
var objectType = this.Compilation.GetSpecialType(SpecialType.System_Object);
- var allTypeParameters = GetAllTypeParameters(_currentFrame);
+ var allTypeParameters = _currentFrame.GetAllTypeParameters();
var additionalTypes = ArrayBuilder.GetInstance();
EENamedTypeSymbol typeVariablesType = null;
@@ -315,10 +307,10 @@ internal CommonPEModuleBuilder CompileGetLocals(
}
// Hoisted method parameters (represented as locals in the EE).
- int ordinal = 0;
if (!_hoistedParameterNames.IsEmpty)
{
- foreach (var local in _localsForBinding)
+ int localIndex = 0;
+ foreach(var local in _localsForBinding)
{
// Since we are showing hoisted method parameters first, the parameters may appear out of order
// in the Locals window if only some of the parameters are hoisted. This is consistent with the
@@ -326,36 +318,39 @@ internal CommonPEModuleBuilder CompileGetLocals(
var localName = local.Name;
if (_hoistedParameterNames.Contains(local.Name))
{
- AppendLocalAndMethod(localBuilder, methodBuilder, localName, this.GetLocalMethod, container, ordinal, GetLocalResultFlags(local));
+ AppendLocalAndMethod(localBuilder, methodBuilder, localName, this.GetLocalMethod, container, localIndex, GetLocalResultFlags(local));
}
- ordinal++;
+
+ localIndex++;
}
}
// Method parameters (except those that have been hoisted).
- ordinal = m.IsStatic ? 0 : 1;
+ int parameterIndex = m.IsStatic ? 0 : 1;
foreach (var parameter in m.Parameters)
{
var parameterName = parameter.Name;
if (!_hoistedParameterNames.Contains(parameterName))
{
- AppendLocalAndMethod(localBuilder, methodBuilder, parameterName, this.GetParameterMethod, container, ordinal, DkmClrCompilationResultFlags.None);
+ AppendLocalAndMethod(localBuilder, methodBuilder, parameterName, this.GetParameterMethod, container, parameterIndex, DkmClrCompilationResultFlags.None);
}
- ordinal++;
+
+ parameterIndex++;
}
if (!argumentsOnly)
{
// Locals.
- ordinal = 0;
+ int localIndex = 0;
foreach (var local in _localsForBinding)
{
var localName = local.Name;
if (!_hoistedParameterNames.Contains(localName))
{
- AppendLocalAndMethod(localBuilder, methodBuilder, localName, this.GetLocalMethod, container, ordinal, GetLocalResultFlags(local));
+ AppendLocalAndMethod(localBuilder, methodBuilder, localName, this.GetLocalMethod, container, localIndex, GetLocalResultFlags(local));
}
- ordinal++;
+
+ localIndex++;
}
// "Type variables".
@@ -401,7 +396,7 @@ private static void AppendLocalAndMethod(
string name,
Func getMethod,
EENamedTypeSymbol container,
- int ordinal,
+ int localOrParameterIndex,
DkmClrCompilationResultFlags resultFlags)
{
// Note: The native EE doesn't do this, but if we don't escape keyword identifiers,
@@ -409,7 +404,7 @@ private static void AppendLocalAndMethod(
// which it can't do correctly without semantic information.
name = SyntaxHelpers.EscapeKeywordIdentifiers(name);
var methodName = GetNextMethodName(methodBuilder);
- var method = getMethod(container, methodName, name, ordinal);
+ var method = getMethod(container, methodName, name, localOrParameterIndex);
localBuilder.Add(new LocalAndMethod(name, methodName, resultFlags));
methodBuilder.Add(method);
}
@@ -446,23 +441,23 @@ internal EEMethodSymbol CreateMethod(
generateMethodBody);
}
- private EEMethodSymbol GetLocalMethod(EENamedTypeSymbol container, string methodName, string localName, int index)
+ private EEMethodSymbol GetLocalMethod(EENamedTypeSymbol container, string methodName, string localName, int localIndex)
{
var syntax = SyntaxFactory.IdentifierName(localName);
return this.CreateMethod(container, methodName, syntax, (method, diagnostics) =>
{
- var local = method.LocalsForBinding[index];
+ var local = method.LocalsForBinding[localIndex];
var expression = new BoundLocal(syntax, local, constantValueOpt: local.GetConstantValue(null, null, diagnostics), type: local.Type) { WasCompilerGenerated = true };
return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true };
});
}
- private EEMethodSymbol GetParameterMethod(EENamedTypeSymbol container, string methodName, string parameterName, int ordinal)
+ private EEMethodSymbol GetParameterMethod(EENamedTypeSymbol container, string methodName, string parameterName, int parameterIndex)
{
var syntax = SyntaxFactory.IdentifierName(parameterName);
return this.CreateMethod(container, methodName, syntax, (method, diagnostics) =>
{
- var parameter = method.Parameters[ordinal];
+ var parameter = method.Parameters[parameterIndex];
var expression = new BoundParameter(syntax, parameter) { WasCompilerGenerated = true };
return new BoundReturnStatement(syntax, expression) { WasCompilerGenerated = true };
});
diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/SymbolExtensions.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/SymbolExtensions.cs
new file mode 100644
index 0000000000000..d498e56290b11
--- /dev/null
+++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/SymbolExtensions.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+
+namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
+{
+ internal static class SymbolExtensions
+ {
+ internal static ImmutableArray GetAllTypeParameters(this MethodSymbol method)
+ {
+ var builder = ArrayBuilder.GetInstance();
+ method.ContainingType.GetAllTypeParameters(builder);
+ builder.AddRange(method.TypeParameters);
+ return builder.ToImmutableAndFree();
+ }
+ }
+}
diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs
index de325e47410c0..64259534d85ab 100644
--- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs
+++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EEMethodSymbol.cs
@@ -19,6 +19,15 @@ namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
///
internal sealed class EEMethodSymbol : MethodSymbol
{
+ // We only create a single EE method (per EE type) that represents an arbitrary expression,
+ // whose lowering may produce synthesized members (lambdas, dynamic sites, etc).
+ // We may thus assume that the method ordinal is always 0.
+ //
+ // Consider making the implementation more flexible in order to avoid this assumption.
+ // In future we might need to compile multiple expression and then we'll need to assign
+ // a unique method ordinal to each of them to avoid duplicate synthesized member names.
+ private const int _methodOrdinal = 0;
+
internal readonly TypeMap TypeMap;
internal readonly MethodSymbol SubstitutedSourceMethod;
internal readonly ImmutableArray Locals;
@@ -31,6 +40,7 @@ internal sealed class EEMethodSymbol : MethodSymbol
private readonly ImmutableArray _parameters;
private readonly ParameterSymbol _thisParameter;
private readonly ImmutableDictionary _displayClassVariables;
+
///
/// Invoked at most once to generate the method body.
/// (If the compilation has no errors, it will be invoked
@@ -472,7 +482,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
body = LocalRewriter.Rewrite(
compilation: this.DeclaringCompilation,
method: this,
- methodOrdinal: 0,
+ methodOrdinal: _methodOrdinal,
containingType: _container,
statement: body,
compilationState: compilationState,
@@ -544,7 +554,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
thisType: this.SubstitutedSourceMethod.ContainingType,
thisParameter: _thisParameter,
method: this,
- methodOrdinal: 0,
+ methodOrdinal: _methodOrdinal,
closureDebugInfoBuilder: closureDebugInfoBuilder,
lambdaDebugInfoBuilder: lambdaDebugInfoBuilder,
slotAllocatorOpt: null,
diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/InstructionDecoderTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/InstructionDecoderTests.cs
index 7e33eba502981..26f3a00c48a8b 100644
--- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/InstructionDecoderTests.cs
+++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/InstructionDecoderTests.cs
@@ -1,7 +1,10 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System;
using System.Diagnostics;
+using System.Linq;
using System.Reflection.Metadata.Ecma335;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
@@ -14,8 +17,90 @@ namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
public class InstructionDecoderTests : ExpressionCompilerTestBase
{
+ [Fact]
+ void GetNameGenerics()
+ {
+ var source = @"
+using System;
+class Class1
+{
+ void M1(Action a)
+ {
+ }
+ void M2(Action a)
+ {
+ }
+ void M3(Action a)
+ {
+ }
+}";
+
+ Assert.Equal(
+ "Class1.M1(System.Action a)",
+ GetName(source, "Class1.M1", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types));
+
+ Assert.Equal(
+ "Class1.M2(System.Action a)",
+ GetName(source, "Class1.M2", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types));
+
+ Assert.Equal(
+ "Class1.M3(System.Action a)",
+ GetName(source, "Class1.M3", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types));
+
+ Assert.Equal(
+ "Class1.M1(System.Action a)",
+ GetName(source, "Class1.M1", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, new[] { typeof(string), typeof(decimal) }));
+
+ Assert.Equal(
+ "Class1.M2(System.Action a)",
+ GetName(source, "Class1.M2", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, new[] { typeof(string), typeof(decimal) }));
+
+ Assert.Equal(
+ "Class1.M3(System.Action a)",
+ GetName(source, "Class1.M3", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, new[] { typeof(string), typeof(decimal) }));
+ }
+
+ [Fact]
+ void GetNameNullTypeArguments()
+ {
+ var source = @"
+using System;
+class Class1
+{
+ void M(Action a)
+ {
+ }
+}";
+
+ Assert.Equal(
+ "Class1.M(System.Action a)",
+ GetName(source, "Class1.M", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, typeArguments: new Type[] { null, null }));
+
+ Assert.Equal(
+ "Class1.M(System.Action a)",
+ GetName(source, "Class1.M", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, typeArguments: new[] { typeof(string), null }));
+
+ Assert.Equal(
+ "Class1.M(System.Action a)",
+ GetName(source, "Class1.M", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, typeArguments: new[] { null, typeof(decimal) }));
+ }
+
+ [Fact]
+ void GetNameGenericArgumentTypeNotInReferences()
+ {
+ var source = @"
+class Class1
+{
+}";
+
+ var serializedTypeArgumentName = "Class1, " + nameof(InstructionDecoderTests) + ", Culture=neutral, PublicKeyToken=null";
+ Assert.Equal(
+ "System.Collections.Generic.Comparer.Create(System.Comparison comparison)",
+ GetName(source, "System.Collections.Generic.Comparer.Create", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, typeArguments: new[] { serializedTypeArgumentName }));
+ }
+
[Fact, WorkItem(1107977)]
- public void GetNameGenericAsync()
+ void GetNameGenericAsync()
{
var source = @"
using System.Threading.Tasks;
@@ -29,12 +114,12 @@ static async Task M(T x)
}";
Assert.Equal(
- "C.M(T x)",
- GetName(source, "C.d__0.MoveNext", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types));
+ "C.M(System.Exception x)",
+ GetName(source, "C.d__0.MoveNext", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, new[] { typeof(Exception) }));
}
[Fact]
- public void GetNameLambda()
+ void GetNameLambda()
{
var source = @"
using System;
@@ -52,7 +137,7 @@ void M()
}
[Fact]
- public void GetNameGenericLambda()
+ void GetNameGenericLambda()
{
var source = @"
using System;
@@ -65,12 +150,12 @@ void M() where U : T
}";
Assert.Equal(
- "C.M.AnonymousMethod__0_0(U u)",
- GetName(source, "C.<>c__0.b__0_0", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types));
+ "C.M.AnonymousMethod__0_0(System.ArgumentException u)",
+ GetName(source, "C.<>c__0.b__0_0", DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types, new[] { typeof(Exception), typeof(ArgumentException) }));
}
[Fact]
- public void GetNameProperties()
+ void GetNameProperties()
{
var source = @"
class C
@@ -101,7 +186,7 @@ int this[object x]
}
[Fact]
- public void GetNameExplicitInterfaceImplementation()
+ void GetNameExplicitInterfaceImplementation()
{
var source = @"
using System;
@@ -116,7 +201,7 @@ void IDisposable.Dispose() { }
}
[Fact]
- public void GetNameExtensionMethod()
+ void GetNameExtensionMethod()
{
var source = @"
static class Extensions
@@ -130,7 +215,7 @@ static void M(this string @this) { }
}
[Fact]
- public void GetNameArgumentFlagsNone()
+ void GetNameArgumentFlagsNone()
{
var source = @"
static class C
@@ -148,41 +233,154 @@ static void M2(int x, int y) { }
GetName(source, "C.M2", DkmVariableInfoFlags.None));
}
- private string GetName(string source, string methodName, DkmVariableInfoFlags argumentFlags, params string[] argumentValues)
+ [Fact]
+ void GetReturnTypeNamePrimitive()
+ {
+ var source = @"
+static class C
+{
+ static uint M1() { return 42; }
+}";
+
+ Assert.Equal("uint", GetReturnTypeName(source, "C.M1"));
+ }
+
+ [Fact]
+ void GetReturnTypeNameNested()
+ {
+ var source = @"
+static class C
+{
+ static N.D.E M1() { return default(N.D.E); }
+}
+namespace N
+{
+ class D
+ {
+ internal struct E
+ {
+ }
+ }
+}";
+
+ Assert.Equal("N.D.E", GetReturnTypeName(source, "C.M1"));
+ }
+
+ [Fact]
+ void GetReturnTypeNameGenericOfPrimitive()
+ {
+ var source = @"
+using System;
+class C
+{
+ Action M1() { return null; }
+}";
+
+ Assert.Equal("System.Action", GetReturnTypeName(source, "C.M1"));
+ }
+
+ [Fact]
+ void GetReturnTypeNameGenericOfNested()
+ {
+ var source = @"
+using System;
+class C
+{
+ Action M1() { return null; }
+ class D
+ {
+ }
+}";
+
+ Assert.Equal("System.Action", GetReturnTypeName(source, "C.M1"));
+ }
+
+ [Fact]
+ void GetReturnTypeNameGenericOfGeneric()
+ {
+ var source = @"
+using System;
+class C
+{
+ Action> M1() { return null; }
+}";
+
+ Assert.Equal("System.Action>", GetReturnTypeName(source, "C.M1", new[] { typeof(object) }));
+ }
+
+ private string GetName(string source, string methodName, DkmVariableInfoFlags argumentFlags, Type[] typeArguments = null, string[] argumentValues = null)
+ {
+ var serializedTypeArgumentNames = typeArguments?.Select(t => t?.AssemblyQualifiedName).ToArray();
+ return GetName(source, methodName, argumentFlags, serializedTypeArgumentNames, argumentValues);
+ }
+
+ private string GetName(string source, string methodName, DkmVariableInfoFlags argumentFlags, string[] typeArguments, string[] argumentValues = null)
{
Debug.Assert((argumentFlags & (DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types)) == argumentFlags,
"Unexpected argumentFlags", "argumentFlags = {0}", argumentFlags);
- var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugDll);
- var runtime = CreateRuntimeInstance(compilation);
- var moduleInstances = runtime.Modules;
- var blocks = moduleInstances.SelectAsArray(m => m.MetadataBlock);
- compilation = blocks.ToCompilation();
- var frame = (PEMethodSymbol)GetMethodOrTypeBySignature(compilation, methodName);
+ var instructionDecoder = CSharpInstructionDecoder.Instance;
+ var method = GetConstructedMethod(source, methodName, typeArguments, instructionDecoder);
- // Once we have the method token, we want to look up the method (again)
- // using the same helper as the product code. This helper will also map
- // async/iterator "MoveNext" methods to the original source method.
- var method = compilation.GetSourceMethod(
- ((PEModuleSymbol)frame.ContainingModule).Module.GetModuleVersionIdOrThrow(),
- MetadataTokens.GetToken(frame.Handle));
var includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types);
var includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names);
ArrayBuilder builder = null;
- if (argumentValues.Length > 0)
+ if (argumentValues != null)
{
+ Assert.InRange(argumentValues.Length, 1, int.MaxValue);
builder = ArrayBuilder.GetInstance();
builder.AddRange(argumentValues);
}
- var frameDecoder = CSharpInstructionDecoder.Instance;
- var frameName = frameDecoder.GetName(method, includeParameterTypes, includeParameterNames, builder);
+ var name = instructionDecoder.GetName(method, includeParameterTypes, includeParameterNames, builder);
if (builder != null)
{
builder.Free();
}
- return frameName;
+ return name;
+ }
+
+ private string GetReturnTypeName(string source, string methodName, Type[] typeArguments = null)
+ {
+ var instructionDecoder = CSharpInstructionDecoder.Instance;
+ var serializedTypeArgumentNames = typeArguments?.Select(t => (t != null) ? t.AssemblyQualifiedName : null).ToArray();
+ var method = GetConstructedMethod(source, methodName, serializedTypeArgumentNames, instructionDecoder);
+
+ return instructionDecoder.GetReturnTypeName(method);
+ }
+
+ private MethodSymbol GetConstructedMethod(string source, string methodName, string[] serializedTypeArgumentNames, CSharpInstructionDecoder instructionDecoder)
+ {
+ var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugDll, assemblyName: nameof(InstructionDecoderTests));
+ var runtime = CreateRuntimeInstance(compilation);
+ var moduleInstances = runtime.Modules;
+ var blocks = moduleInstances.SelectAsArray(m => m.MetadataBlock);
+ compilation = blocks.ToCompilation();
+ var frame = (PEMethodSymbol)GetMethodOrTypeBySignature(compilation, methodName);
+
+ // Once we have the method token, we want to look up the method (again)
+ // using the same helper as the product code. This helper will also map
+ // async/iterator "MoveNext" methods to the original source method.
+ MethodSymbol method = compilation.GetSourceMethod(
+ ((PEModuleSymbol)frame.ContainingModule).Module.GetModuleVersionIdOrThrow(),
+ MetadataTokens.GetToken(frame.Handle));
+ if (serializedTypeArgumentNames != null)
+ {
+ Assert.NotEmpty(serializedTypeArgumentNames);
+ var typeParameters = instructionDecoder.GetAllTypeParameters(method);
+ Assert.NotEmpty(typeParameters);
+ var typeNameDecoder = new EETypeNameDecoder(compilation, (PEModuleSymbol)method.ContainingModule);
+ // Use the same helper method as the FrameDecoder to get the TypeSymbols for the
+ // generic type arguments (rather than using EETypeNameDecoder directly).
+ var typeArguments = instructionDecoder.GetTypeSymbols(compilation, method, serializedTypeArgumentNames);
+ if (!typeArguments.IsEmpty)
+ {
+ method = instructionDecoder.ConstructMethod(method, typeParameters, typeArguments);
+ }
+ }
+
+ return method;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.csproj b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.csproj
index f8f350da30a71..4a5b4f895fd94 100644
--- a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.csproj
+++ b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionCompiler.csproj
@@ -18,9 +18,6 @@
-
- Shared\MetadataReaderPdbExtensions.cs
-
Shared\SymUnmanagedReaderExtensions.cs
diff --git a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionEvaluatorFatalError.cs b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionEvaluatorFatalError.cs
index 30601e88a1587..77d27323a45b7 100644
--- a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionEvaluatorFatalError.cs
+++ b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/ExpressionEvaluatorFatalError.cs
@@ -4,11 +4,12 @@
using System.Diagnostics;
using System.Reflection;
using Microsoft.VisualStudio.Debugger;
+using Roslyn.Utilities;
#if !EXPRESSIONCOMPILER
using Microsoft.CodeAnalysis.ErrorReporting;
-
#endif
+
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
internal static class ExpressionEvaluatorFatalError
@@ -80,5 +81,20 @@ internal static bool CrashIfFailFastEnabled(Exception exception)
return FatalError.Report(exception);
}
+
+ internal delegate bool NonFatalExceptionHandler(Exception exception, string implementationName);
+
+ internal static bool ReportNonFatalException(Exception exception, NonFatalExceptionHandler handler)
+ {
+ if (CrashIfFailFastEnabled(exception))
+ {
+ throw ExceptionUtilities.Unreachable;
+ }
+
+ // Ignore the return value, because we always want to continue after reporting the Exception.
+ handler(exception, nameof(ExpressionEvaluatorFatalError));
+
+ return true;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/FrameDecoder.cs b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/FrameDecoder.cs
index 0ab210df78e5f..f3e1b24a68b84 100644
--- a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/FrameDecoder.cs
+++ b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/FrameDecoder.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Debugger.CallStack;
@@ -19,86 +20,35 @@ namespace Microsoft.CodeAnalysis.ExpressionEvaluator
/// always used C# syntax (but with language-specific "special names"). Since these names are exposed through public
/// APIs, we will remain consistent with the old behavior (for consumers who may be parsing the frame names).
///
- internal abstract class FrameDecoder : IDkmLanguageFrameDecoder
+ internal abstract class FrameDecoder : IDkmLanguageFrameDecoder
+ where TCompilation : Compilation
+ where TMethodSymbol : class, IMethodSymbol
+ where TModuleSymbol : class, IModuleSymbol
+ where TTypeSymbol : class, ITypeSymbol
+ where TTypeParameterSymbol : class, ITypeParameterSymbol
{
- private readonly InstructionDecoder _instructionDecoder;
+ private readonly InstructionDecoder _instructionDecoder;
- internal FrameDecoder(InstructionDecoder instructionDecoder)
+ internal FrameDecoder(InstructionDecoder instructionDecoder)
{
_instructionDecoder = instructionDecoder;
}
- void IDkmLanguageFrameDecoder.GetFrameName(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmVariableInfoFlags argumentFlags, DkmCompletionRoutine completionRoutine)
+ void IDkmLanguageFrameDecoder.GetFrameName(
+ DkmInspectionContext inspectionContext,
+ DkmWorkList workList,
+ DkmStackWalkFrame frame,
+ DkmVariableInfoFlags argumentFlags,
+ DkmCompletionRoutine completionRoutine)
{
try
{
Debug.Assert((argumentFlags & (DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types | DkmVariableInfoFlags.Values)) == argumentFlags,
"Unexpected argumentFlags", "argumentFlags = {0}", argumentFlags);
- var instructionAddress = (DkmClrInstructionAddress)frame.InstructionAddress;
- var includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types);
- var includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names);
-
- if (argumentFlags.Includes(DkmVariableInfoFlags.Values))
- {
- // No need to compute the Expandable bit on
- // argument values since that can be expensive.
- inspectionContext = DkmInspectionContext.Create(
- inspectionContext.InspectionSession,
- inspectionContext.RuntimeInstance,
- inspectionContext.Thread,
- inspectionContext.Timeout,
- inspectionContext.EvaluationFlags | DkmEvaluationFlags.NoExpansion,
- inspectionContext.FuncEvalFlags,
- inspectionContext.Radix,
- inspectionContext.Language,
- inspectionContext.ReturnValue,
- inspectionContext.AdditionalVisualizationData,
- inspectionContext.AdditionalVisualizationDataPriority,
- inspectionContext.ReturnValues);
-
- // GetFrameArguments returns an array of formatted argument values. We'll pass
- // ourselves (GetFrameName) as the continuation of the GetFrameArguments call.
- inspectionContext.GetFrameArguments(
- workList,
- frame,
- result =>
- {
- try
- {
- var builder = ArrayBuilder.GetInstance();
- foreach (var argument in result.Arguments)
- {
- var evaluatedArgument = argument as DkmSuccessEvaluationResult;
- // Not expecting Expandable bit, at least not from this EE.
- Debug.Assert((evaluatedArgument == null) || (evaluatedArgument.Flags & DkmEvaluationResultFlags.Expandable) == 0);
- builder.Add((evaluatedArgument != null) ? evaluatedArgument.Value : null);
- }
-
- var frameName = _instructionDecoder.GetName(instructionAddress, includeParameterTypes, includeParameterNames, builder);
- builder.Free();
- completionRoutine(new DkmGetFrameNameAsyncResult(frameName));
- }
- // TODO: Consider calling DkmComponentManager.ReportCurrentNonFatalException() to
- // trigger a non-fatal Watson when this occurs.
- catch (Exception e) when (!ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e))
- {
- completionRoutine(DkmGetFrameNameAsyncResult.CreateErrorResult(e));
- }
- finally
- {
- foreach (var argument in result.Arguments)
- {
- argument.Close();
- }
- }
- });
- }
- else
- {
- var frameName = _instructionDecoder.GetName(instructionAddress, includeParameterTypes, includeParameterNames, null);
- completionRoutine(new DkmGetFrameNameAsyncResult(frameName));
- }
+ GetNameWithGenericTypeArguments(inspectionContext, workList, frame,
+ onSuccess: method => GetFrameName(inspectionContext, workList, frame, argumentFlags, completionRoutine, method),
+ onFailure: e => completionRoutine(DkmGetFrameNameAsyncResult.CreateErrorResult(e)));
}
catch (Exception e) when (ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e))
{
@@ -106,18 +56,135 @@ void IDkmLanguageFrameDecoder.GetFrameName(DkmInspectionContext inspectionContex
}
}
- void IDkmLanguageFrameDecoder.GetFrameReturnType(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame frame, DkmCompletionRoutine completionRoutine)
+ void IDkmLanguageFrameDecoder.GetFrameReturnType(
+ DkmInspectionContext inspectionContext,
+ DkmWorkList workList,
+ DkmStackWalkFrame frame,
+ DkmCompletionRoutine completionRoutine)
{
try
{
- var returnType = _instructionDecoder.GetReturnType((DkmClrInstructionAddress)frame.InstructionAddress);
- var result = new DkmGetFrameReturnTypeAsyncResult(returnType);
- completionRoutine(result);
+ GetNameWithGenericTypeArguments(inspectionContext, workList, frame,
+ onSuccess: method => completionRoutine(new DkmGetFrameReturnTypeAsyncResult(_instructionDecoder.GetReturnTypeName(method))),
+ onFailure: e => completionRoutine(DkmGetFrameReturnTypeAsyncResult.CreateErrorResult(e)));
}
catch (Exception e) when (ExpressionEvaluatorFatalError.CrashIfFailFastEnabled(e))
{
throw ExceptionUtilities.Unreachable;
}
}
+
+ private void GetNameWithGenericTypeArguments(
+ DkmInspectionContext inspectionContext,
+ DkmWorkList workList,
+ DkmStackWalkFrame frame,
+ Action onSuccess,
+ Action onFailure)
+ {
+ // NOTE: We could always call GetClrGenericParameters, pass them to GetMethod and have that
+ // return a constructed method symbol, but it seems unwise to call GetClrGenericParameters
+ // for all frames (as this call requires a round-trip to the debuggee process).
+ var instructionAddress = (DkmClrInstructionAddress)frame.InstructionAddress;
+ var compilation = _instructionDecoder.GetCompilation(instructionAddress);
+ var method = _instructionDecoder.GetMethod(compilation, instructionAddress);
+ var typeParameters = _instructionDecoder.GetAllTypeParameters(method);
+ if (!typeParameters.IsEmpty)
+ {
+ frame.GetClrGenericParameters(
+ workList,
+ result =>
+ {
+ try
+ {
+ var typeArguments = _instructionDecoder.GetTypeSymbols(compilation, method, result.ParameterTypeNames);
+ if (!typeArguments.IsEmpty)
+ {
+ method = _instructionDecoder.ConstructMethod(method, typeParameters, typeArguments);
+ }
+ onSuccess(method);
+ }
+ catch (Exception e) when (ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException))
+ {
+ onFailure(e);
+ }
+ });
+ }
+ else
+ {
+ onSuccess(method);
+ }
+ }
+
+ private void GetFrameName(
+ DkmInspectionContext inspectionContext,
+ DkmWorkList workList,
+ DkmStackWalkFrame frame,
+ DkmVariableInfoFlags argumentFlags,
+ DkmCompletionRoutine completionRoutine,
+ TMethodSymbol method)
+ {
+ var includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types);
+ var includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names);
+
+ if (argumentFlags.Includes(DkmVariableInfoFlags.Values))
+ {
+ // No need to compute the Expandable bit on
+ // argument values since that can be expensive.
+ inspectionContext = DkmInspectionContext.Create(
+ inspectionContext.InspectionSession,
+ inspectionContext.RuntimeInstance,
+ inspectionContext.Thread,
+ inspectionContext.Timeout,
+ inspectionContext.EvaluationFlags | DkmEvaluationFlags.NoExpansion,
+ inspectionContext.FuncEvalFlags,
+ inspectionContext.Radix,
+ inspectionContext.Language,
+ inspectionContext.ReturnValue,
+ inspectionContext.AdditionalVisualizationData,
+ inspectionContext.AdditionalVisualizationDataPriority,
+ inspectionContext.ReturnValues);
+
+ // GetFrameArguments returns an array of formatted argument values. We'll pass
+ // ourselves (GetFrameName) as the continuation of the GetFrameArguments call.
+ inspectionContext.GetFrameArguments(
+ workList,
+ frame,
+ result =>
+ {
+ var argumentValues = result.Arguments;
+ try
+ {
+ var builder = ArrayBuilder.GetInstance();
+ foreach (var argument in argumentValues)
+ {
+ var formattedArgument = argument as DkmSuccessEvaluationResult;
+ // Not expecting Expandable bit, at least not from this EE.
+ Debug.Assert((formattedArgument == null) || (formattedArgument.Flags & DkmEvaluationResultFlags.Expandable) == 0);
+ builder.Add(formattedArgument?.Value);
+ }
+
+ var frameName = _instructionDecoder.GetName(method, includeParameterTypes, includeParameterNames, builder);
+ builder.Free();
+ completionRoutine(new DkmGetFrameNameAsyncResult(frameName));
+ }
+ catch (Exception e) when (ExpressionEvaluatorFatalError.ReportNonFatalException(e, DkmComponentManager.ReportCurrentNonFatalException))
+ {
+ completionRoutine(DkmGetFrameNameAsyncResult.CreateErrorResult(e));
+ }
+ finally
+ {
+ foreach (var argument in argumentValues)
+ {
+ argument.Close();
+ }
+ }
+ });
+ }
+ else
+ {
+ var frameName = _instructionDecoder.GetName(method, includeParameterTypes, includeParameterNames, null);
+ completionRoutine(new DkmGetFrameNameAsyncResult(frameName));
+ }
+ }
}
}
diff --git a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/InstructionDecoder.cs b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/InstructionDecoder.cs
index be947e272e0a1..80126b5f5e6bd 100644
--- a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/InstructionDecoder.cs
+++ b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/InstructionDecoder.cs
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System.Collections.Immutable;
using System.Diagnostics;
using System.Text;
using Microsoft.CodeAnalysis.Collections;
@@ -7,13 +8,12 @@
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
- internal abstract class InstructionDecoder
- {
- internal abstract string GetName(DkmClrInstructionAddress instructionAddress, bool includeParameterTypes, bool includeParameterNames, ArrayBuilder argumentValues);
- internal abstract string GetReturnType(DkmClrInstructionAddress instructionAddress);
- }
-
- internal abstract class InstructionDecoder : InstructionDecoder where TMethodSymbol : class, IMethodSymbol
+ internal abstract class InstructionDecoder
+ where TCompilation : Compilation
+ where TMethodSymbol : class, IMethodSymbol
+ where TModuleSymbol : class, IModuleSymbol
+ where TTypeSymbol : class, ITypeSymbol
+ where TTypeParameterSymbol : class, ITypeParameterSymbol
{
internal static readonly SymbolDisplayFormat DisplayFormat = new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
@@ -21,21 +21,18 @@ internal abstract class InstructionDecoder : InstructionDecoder w
memberOptions: SymbolDisplayMemberOptions.IncludeContainingType | SymbolDisplayMemberOptions.IncludeExplicitInterface,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
- internal override string GetName(DkmClrInstructionAddress instructionAddress, bool includeParameterTypes, bool includeParameterNames, ArrayBuilder argumentValues)
- {
- var method = this.GetMethod(instructionAddress);
- return this.GetName(method, includeParameterTypes, includeParameterNames, argumentValues);
- }
+ internal abstract void AppendFullName(StringBuilder builder, TMethodSymbol method);
- internal override string GetReturnType(DkmClrInstructionAddress instructionAddress)
- {
- var method = this.GetMethod(instructionAddress);
- return method.ReturnType.ToDisplayString(DisplayFormat);
- }
+ ///
+ /// Constructs a method and any of its generic containing types using the specified .
+ ///
+ internal abstract TMethodSymbol ConstructMethod(TMethodSymbol method, ImmutableArray typeParameters, ImmutableArray typeArguments);
- internal abstract void AppendFullName(StringBuilder builder, TMethodSymbol method);
+ internal abstract ImmutableArray GetAllTypeParameters(TMethodSymbol method);
+
+ internal abstract TCompilation GetCompilation(DkmClrInstructionAddress instructionAddress);
- internal abstract TMethodSymbol GetMethod(DkmClrInstructionAddress instructionAddress);
+ internal abstract TMethodSymbol GetMethod(TCompilation compilation, DkmClrInstructionAddress instructionAddress);
internal string GetName(TMethodSymbol method, bool includeParameterTypes, bool includeParameterNames, ArrayBuilder argumentValues = null)
{
@@ -96,5 +93,33 @@ internal string GetName(TMethodSymbol method, bool includeParameterTypes, bool i
return pooled.ToStringAndFree();
}
+
+ internal string GetReturnTypeName(TMethodSymbol method)
+ {
+ return method.ReturnType.ToDisplayString(DisplayFormat);
+ }
+
+ internal abstract TypeNameDecoder GetTypeNameDecoder(TCompilation compilation, TMethodSymbol method);
+
+ internal ImmutableArray GetTypeSymbols(TCompilation compilation, TMethodSymbol method, string[] serializedTypeNames)
+ {
+ var builder = ArrayBuilder.GetInstance();
+ foreach (var name in serializedTypeNames)
+ {
+ // The list of type names will include null values if type arguments are not available.
+ // It seems unlikely that only some type arguments will be missing (and it also seems
+ // like very little incremental value to include only some of the arguments), so we'll
+ // keep things simple and omit all type arguments if any are missing.
+ if (name == null)
+ {
+ builder.Free();
+ return ImmutableArray.Empty;
+ }
+
+ var typeNameDecoder = GetTypeNameDecoder(compilation, method);
+ builder.Add(typeNameDecoder.GetTypeSymbolForSerializedType(name));
+ }
+ return builder.ToImmutableAndFree();
+ }
}
}
diff --git a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/LanguageInstructionDecoder.cs b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/LanguageInstructionDecoder.cs
index d5a7b0a357593..bbed5e6088945 100644
--- a/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/LanguageInstructionDecoder.cs
+++ b/src/ExpressionEvaluator/Core/Source/ExpressionCompiler/LanguageInstructionDecoder.cs
@@ -17,11 +17,16 @@ namespace Microsoft.CodeAnalysis.ExpressionEvaluator
///
/// This class provides function name information for the Breakpoints window.
///
- internal abstract class LanguageInstructionDecoder : IDkmLanguageInstructionDecoder where TMethodSymbol : class, IMethodSymbol
+ internal abstract class LanguageInstructionDecoder : IDkmLanguageInstructionDecoder
+ where TCompilation : Compilation
+ where TMethodSymbol : class, IMethodSymbol
+ where TModuleSymbol : class, IModuleSymbol
+ where TTypeSymbol : class, ITypeSymbol
+ where TTypeParameterSymbol : class, ITypeParameterSymbol
{
- private readonly InstructionDecoder _instructionDecoder;
+ private readonly InstructionDecoder _instructionDecoder;
- internal LanguageInstructionDecoder(InstructionDecoder instructionDecoder)
+ internal LanguageInstructionDecoder(InstructionDecoder instructionDecoder)
{
_instructionDecoder = instructionDecoder;
}
@@ -37,7 +42,9 @@ string IDkmLanguageInstructionDecoder.GetMethodName(DkmLanguageInstructionAddres
Debug.Assert((argumentFlags & (DkmVariableInfoFlags.FullNames | DkmVariableInfoFlags.Names | DkmVariableInfoFlags.Types)) == argumentFlags,
"Unexpected argumentFlags", "argumentFlags = {0}", argumentFlags);
- var method = _instructionDecoder.GetMethod((DkmClrInstructionAddress)languageInstructionAddress.Address);
+ var instructionAddress = (DkmClrInstructionAddress)languageInstructionAddress.Address;
+ var compilation = _instructionDecoder.GetCompilation(instructionAddress);
+ var method = _instructionDecoder.GetMethod(compilation, instructionAddress);
var includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types);
var includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names);
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationContext.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationContext.vb
index 1b42c478cc57d..ceb02216d1bbb 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationContext.vb
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/CompilationContext.vb
@@ -1,4 +1,6 @@
-Imports System
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+Imports System
Imports System.Collections.Immutable
Imports System.Runtime.InteropServices
Imports System.Threading
@@ -173,13 +175,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Return moduleBuilder
End Function
- Private Shared Function GetAllTypeParameters(method As MethodSymbol) As ImmutableArray(Of TypeParameterSymbol)
- Dim builder = ArrayBuilder(Of TypeParameterSymbol).GetInstance()
- method.ContainingType.GetAllTypeParameters(builder)
- builder.AddRange(method.TypeParameters)
- Return builder.ToImmutableAndFree()
- End Function
-
Private Shared Function GetNextMethodName(builder As ArrayBuilder(Of MethodSymbol)) As String
' NOTE: These names are consumed by Concord, so there's no native precedent.
Return String.Format("<>m{0}", builder.Count)
@@ -242,39 +237,43 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
End If
' Hoisted method parameters (represented as locals in the EE).
- Dim ordinal As Integer = 0
If Not _hoistedParameterNames.IsEmpty Then
+ Dim localIndex As Integer = 0
+
For Each local In _localsForBinding
' Since we are showing hoisted method parameters first, the parameters may appear out of order
' in the Locals window if only some of the parameters are hoisted. This is consistent with the
' behavior of the old EE.
Dim localName = local.Name
If _hoistedParameterNames.Contains(local.Name) Then
- AppendLocalAndMethod(localBuilder, methodBuilder, localName, AddressOf Me.GetLocalMethod, container, ordinal, GetLocalResultFlags(local))
+ AppendLocalAndMethod(localBuilder, methodBuilder, localName, AddressOf Me.GetLocalMethod, container, localIndex, GetLocalResultFlags(local))
End If
- ordinal += 1
+
+ localIndex += 1
Next
End If
' Method parameters (except those that have been hoisted).
- ordinal = If(m.IsShared, 0, 1)
+ Dim parameterIndex = If(m.IsShared, 0, 1)
For Each parameter In m.Parameters
Dim parameterName = parameter.Name
If Not _hoistedParameterNames.Contains(parameterName) Then
- AppendLocalAndMethod(localBuilder, methodBuilder, parameterName, AddressOf Me.GetParameterMethod, container, ordinal, DkmClrCompilationResultFlags.None)
+ AppendLocalAndMethod(localBuilder, methodBuilder, parameterName, AddressOf Me.GetParameterMethod, container, parameterIndex, DkmClrCompilationResultFlags.None)
End If
- ordinal += 1
+
+ parameterIndex += 1
Next
If Not argumentsOnly Then
' Locals.
- ordinal = 0
+ Dim localIndex As Integer = 0
For Each local In _localsForBinding
Dim localName = local.Name
If Not _hoistedParameterNames.Contains(localName) Then
- AppendLocalAndMethod(localBuilder, methodBuilder, localName, AddressOf Me.GetLocalMethod, container, ordinal, GetLocalResultFlags(local))
+ AppendLocalAndMethod(localBuilder, methodBuilder, localName, AddressOf Me.GetLocalMethod, container, localIndex, GetLocalResultFlags(local))
End If
- ordinal += 1
+
+ localIndex += 1
Next
' "Type variables".
@@ -319,7 +318,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
name As String,
getMethod As Func(Of EENamedTypeSymbol, String, String, Integer, MethodSymbol),
container As EENamedTypeSymbol,
- ordinal As Integer,
+ localOrParameterIndex As Integer,
resultFlags As DkmClrCompilationResultFlags)
' Note: The native EE doesn't do this, but if we don't escape keyword identifiers,
@@ -327,7 +326,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
' which it can't do correctly without semantic information.
name = SyntaxHelpers.EscapeKeywordIdentifiers(name)
Dim methodName = GetNextMethodName(methodBuilder)
- Dim method = getMethod(container, methodName, name, ordinal)
+ Dim method = getMethod(container, methodName, name, localOrParameterIndex)
localBuilder.Add(New LocalAndMethod(name, methodName, resultFlags))
methodBuilder.Add(method)
End Sub
@@ -365,27 +364,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
generateMethodBody)
End Function
- Private Function GetLocalMethod(container As EENamedTypeSymbol, methodName As String, localName As String, index As Integer) As EEMethodSymbol
+ Private Function GetLocalMethod(container As EENamedTypeSymbol, methodName As String, localName As String, localIndex As Integer) As EEMethodSymbol
Dim syntax = SyntaxFactory.IdentifierName(localName)
Return Me.CreateMethod(
container,
methodName,
syntax,
Function(method, diagnostics)
- Dim local = method.LocalsForBinding(index)
+ Dim local = method.LocalsForBinding(localIndex)
Dim expression = New BoundLocal(syntax, local, isLValue:=False, type:=local.Type).MakeCompilerGenerated()
Return New BoundReturnStatement(syntax, expression, Nothing, Nothing).MakeCompilerGenerated()
End Function)
End Function
- Private Function GetParameterMethod(container As EENamedTypeSymbol, methodName As String, parameterName As String, index As Integer) As EEMethodSymbol
+ Private Function GetParameterMethod(container As EENamedTypeSymbol, methodName As String, parameterName As String, parameterIndex As Integer) As EEMethodSymbol
Dim syntax = SyntaxFactory.IdentifierName(parameterName)
Return Me.CreateMethod(
container,
methodName,
syntax,
Function(method, diagnostics)
- Dim parameter = method.Parameters(index)
+ Dim parameter = method.Parameters(parameterIndex)
Dim expression = New BoundParameter(syntax, parameter, isLValue:=False, type:=parameter.Type).MakeCompilerGenerated()
Return New BoundReturnStatement(syntax, expression, Nothing, Nothing).MakeCompilerGenerated()
End Function)
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/SymbolExtensions.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/SymbolExtensions.vb
index 4c6b96d59311e..b2f418a0b8278 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/SymbolExtensions.vb
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/SymbolExtensions.vb
@@ -1,4 +1,7 @@
-Imports System.Runtime.CompilerServices
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+Imports System.Collections.Immutable
+Imports System.Runtime.CompilerServices
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
@@ -59,5 +62,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Friend Function IsStateMachineType(type As TypeSymbol) As Boolean
Return type.Name.StartsWith(StringConstants.StateMachineTypeNamePrefix, StringComparison.Ordinal)
End Function
+
+
+ Friend Function GetAllTypeParameters(method As MethodSymbol) As ImmutableArray(Of TypeParameterSymbol)
+ Dim builder = ArrayBuilder(Of TypeParameterSymbol).GetInstance()
+ method.ContainingType.GetAllTypeParameters(builder)
+ builder.AddRange(method.TypeParameters)
+ Return builder.ToImmutableAndFree()
+ End Function
End Module
End Namespace
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicFrameDecoder.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicFrameDecoder.vb
index fc1aa18494b38..dc71a62a05c4a 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicFrameDecoder.vb
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicFrameDecoder.vb
@@ -1,9 +1,13 @@
-Imports Microsoft.CodeAnalysis.ExpressionEvaluator
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+Imports Microsoft.CodeAnalysis.ExpressionEvaluator
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
- Friend NotInheritable Class VisualBasicFrameDecoder : Inherits FrameDecoder
+ Friend NotInheritable Class VisualBasicFrameDecoder : Inherits FrameDecoder(Of VisualBasicCompilation, MethodSymbol, PEModuleSymbol, TypeSymbol, TypeParameterSymbol)
Public Sub New()
MyBase.New(VisualBasicInstructionDecoder.Instance)
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicInstructionDecoder.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicInstructionDecoder.vb
index ba82c0aac338b..c4fac085d08f5 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicInstructionDecoder.vb
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicInstructionDecoder.vb
@@ -1,6 +1,8 @@
-Imports System.Runtime.InteropServices
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.VisualStudio.Debugger
Imports Microsoft.VisualStudio.Debugger.Clr
@@ -8,7 +10,7 @@ Imports System.Text
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
- Friend NotInheritable Class VisualBasicInstructionDecoder : Inherits InstructionDecoder(Of PEMethodSymbol)
+ Friend NotInheritable Class VisualBasicInstructionDecoder : Inherits InstructionDecoder(Of VisualBasicCompilation, MethodSymbol, PEModuleSymbol, TypeSymbol, TypeParameterSymbol)
' These strings were not localized in the old EE. We'll keep them that way
' so as not to break consumers who may have been parsing frame names...
@@ -18,12 +20,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
'''
''' Singleton instance of (created using default constructor).
'''
- Friend Shared ReadOnly Instance as VisualBasicInstructionDecoder = New VisualBasicInstructionDecoder()
+ Friend Shared ReadOnly Instance As VisualBasicInstructionDecoder = New VisualBasicInstructionDecoder()
Private Sub New()
End Sub
- Friend Overrides Sub AppendFullName(builder As StringBuilder, method As PEMethodSymbol)
+ Friend Overrides Sub AppendFullName(builder As StringBuilder, method As MethodSymbol)
Dim parts = method.ToDisplayParts(DisplayFormat)
Dim numParts = parts.Length
For i = 0 To numParts - 1
@@ -59,9 +61,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Next
End Sub
- Friend Overrides Function GetMethod(instructionAddress As DkmClrInstructionAddress) As PEMethodSymbol
- Dim moduleInstance = instructionAddress.ModuleInstance
- Dim appDomain = moduleInstance.AppDomain
+ Friend Overrides Function ConstructMethod(method As MethodSymbol, typeParameters As ImmutableArray(Of TypeParameterSymbol), typeArguments As ImmutableArray(Of TypeSymbol)) As MethodSymbol
+ Dim methodArity = method.Arity
+ Dim methodArgumentStartIndex = typeParameters.Length - methodArity
+ Dim typeMap = TypeSubstitution.Create(
+ method,
+ ImmutableArray.Create(typeParameters, 0, methodArgumentStartIndex),
+ ImmutableArray.Create(typeArguments, 0, methodArgumentStartIndex))
+ Dim substitutedType = typeMap.SubstituteNamedType(method.ContainingType)
+ method = method.AsMember(substitutedType)
+ If methodArity > 0 Then
+ method = method.Construct(ImmutableArray.Create(typeArguments, methodArgumentStartIndex, methodArity))
+ End If
+ Return method
+ End Function
+
+ Friend Overrides Function GetAllTypeParameters(method As MethodSymbol) As ImmutableArray(Of TypeParameterSymbol)
+ Return method.GetAllTypeParameters()
+ End Function
+
+ Friend Overrides Function GetCompilation(instructionAddress As DkmClrInstructionAddress) As VisualBasicCompilation
+ Dim appDomain = instructionAddress.ModuleInstance.AppDomain
Dim previous = appDomain.GetDataItem(Of VisualBasicMetadataContext)()
Dim metadataBlocks = instructionAddress.Process.GetMetadataBlocks(appDomain)
@@ -73,7 +93,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
appDomain.SetDataItem(DkmDataCreationDisposition.CreateAlways, New VisualBasicMetadataContext(metadataBlocks))
End If
- Return compilation.GetSourceMethod(moduleInstance.Mvid, instructionAddress.MethodId.Token)
+ Return compilation
+ End Function
+
+ Friend Overrides Function GetMethod(compilation As VisualBasicCompilation, instructionAddress As DkmClrInstructionAddress) As MethodSymbol
+ Return compilation.GetSourceMethod(instructionAddress.ModuleInstance.Mvid, instructionAddress.MethodId.Token)
+ End Function
+
+ Friend Overrides Function GetTypeNameDecoder(compilation As VisualBasicCompilation, method As MethodSymbol) As TypeNameDecoder(Of PEModuleSymbol, TypeSymbol)
+ Debug.Assert(TypeOf method Is PEMethodSymbol)
+ Return New EETypeNameDecoder(compilation, DirectCast(method.ContainingModule, PEModuleSymbol))
End Function
End Class
diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicLanguageInstructionDecoder.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicLanguageInstructionDecoder.vb
index cd4ba00673d41..c8fad9add4aa5 100644
--- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicLanguageInstructionDecoder.vb
+++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/VisualBasicLanguageInstructionDecoder.vb
@@ -1,10 +1,13 @@
-Imports Microsoft.CodeAnalysis.ExpressionEvaluator
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+Imports Microsoft.CodeAnalysis.ExpressionEvaluator
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
- Friend NotInheritable Class VisualBasicLanguageInstructionDecoder : Inherits LanguageInstructionDecoder(Of PEMethodSymbol)
+ Friend NotInheritable Class VisualBasicLanguageInstructionDecoder : Inherits LanguageInstructionDecoder(Of VisualBasicCompilation, MethodSymbol, PEModuleSymbol, TypeSymbol, TypeParameterSymbol)
Public Sub New()
MyBase.New(VisualBasicInstructionDecoder.Instance)
diff --git a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTests.vb b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTests.vb
index 5b0f03b1db133..ccc81e7fa618e 100644
--- a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTests.vb
+++ b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ExpressionCompilerTests.vb
@@ -1,4 +1,6 @@
-Imports System.Collections.Immutable
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+Imports System.Collections.Immutable
Imports System.Globalization
Imports System.Reflection.Metadata
Imports System.Threading
diff --git a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/InstructionDecoderTests.vb b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/InstructionDecoderTests.vb
index 1b33fa3b22a4f..93796e17f3f75 100644
--- a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/InstructionDecoderTests.vb
+++ b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/InstructionDecoderTests.vb
@@ -1,4 +1,7 @@
-Imports System.Reflection.Metadata.Ecma335
+' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+Imports System.Reflection.Metadata.Ecma335
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
@@ -20,11 +23,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
'// TODO: string argument values requiring quotes
'// TODO: argument flags == names only, types only, values only
'// TODO: params Argument values
- '// TODO: GetFrameReturnType primitive types
- '// TODO: GetFrameReturnType non-primitive types (nested namespace/class)
- '// TODO: GetFrameReturnType generic(Of non-primitive, nested)
- '// TODO: GetFrameReturnType generic(Of generic)
- '// TODO: GetFrameReturnType generic(Of primitive)
+ '// TODO: generic class/method with 2 or more type parameters
+ '// TODO: generic argument type that is not from a referenced assembly
Public Class InstructionDecoderTests : Inherits ExpressionCompilerTestBase
@@ -85,7 +85,6 @@ Class Class1(Of T)
Sub M3(Of U)(a As Action(Of U))
End Sub
End Class"
- ' TODO: Type parameters should be substituted with type arguments once we have an API to retrieve them.
Assert.Equal(
"Class1(Of T).M1(Of U)(System.Action(Of Integer) a)",
@@ -98,6 +97,52 @@ End Class"
Assert.Equal(
"Class1(Of T).M3(Of U)(System.Action(Of U) a)",
GetName(source, "Class1.M3", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types))
+
+ Assert.Equal(
+ "Class1(Of String).M1(Of Decimal)(System.Action(Of Integer) a)",
+ GetName(source, "Class1.M1", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={GetType(String), GetType(Decimal)}))
+
+ Assert.Equal(
+ "Class1(Of String).M2(Of Decimal)(System.Action(Of String) a)",
+ GetName(source, "Class1.M2", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={GetType(String), GetType(Decimal)}))
+
+ Assert.Equal(
+ "Class1(Of String).M3(Of Decimal)(System.Action(Of Decimal) a)",
+ GetName(source, "Class1.M3", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={GetType(String), GetType(Decimal)}))
+ End Sub
+
+
+ Sub GetNameNullTypeArguments()
+ Dim source = "
+Imports System
+Class Class1(Of T)
+ Sub M(Of U)(a As Action(Of U))
+ End Sub
+End Class"
+
+ Assert.Equal(
+ "Class1(Of T).M(Of U)(System.Action(Of U) a)",
+ GetName(source, "Class1.M", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:=New Type() {Nothing, Nothing}))
+
+ Assert.Equal(
+ "Class1(Of T).M(Of U)(System.Action(Of U) a)",
+ GetName(source, "Class1.M", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={GetType(String), Nothing}))
+
+ Assert.Equal(
+ "Class1(Of T).M(Of U)(System.Action(Of U) a)",
+ GetName(source, "Class1.M", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={Nothing, GetType(Decimal)}))
+ End Sub
+
+
+ Sub GetNameGenericArgumentTypeNotInReferences()
+ Dim source = "
+Class Class1
+End Class"
+
+ Dim serializedTypeArgumentName = "Class1, " & NameOf(InstructionDecoderTests) & ", Culture=neutral, PublicKeyToken=null"
+ Assert.Equal(
+ "System.Collections.Generic.Comparer(Of Class1).Create(System.Comparison(Of Class1) comparison)",
+ GetName(source, "System.Collections.Generic.Comparer.Create", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={serializedTypeArgumentName}))
End Sub
@@ -130,8 +175,8 @@ Class C
End Class"
Assert.Equal(
- "C.M(Of T)(T x)",
- GetName(source, "C.VB$StateMachine_1_M.MoveNext", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types))
+ "C.M(Of Long)(Long x)",
+ GetName(source, "C.VB$StateMachine_1_M.MoveNext", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={GetType(Long)}))
End Sub
@@ -175,10 +220,10 @@ Class Class1(Of T)
Dim f As Func(Of U, T) = Function(u2 As U) u2
End Sub
End Class"
- ' TODO: Type parameter $CLS0 should be substituted with a type argument once we have an API to retrieve it.
+
Assert.Equal(
- "Class1(Of T)..($CLS0 u2)",
- GetName(source, "Class1._Closure$__1._Lambda$__1-1", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types))
+ "Class1(Of System.Exception)..(System.ArgumentException u2)",
+ GetName(source, "Class1._Closure$__1._Lambda$__1-1", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, typeArguments:={GetType(Exception), GetType(ArgumentException)}))
End Sub
@@ -196,7 +241,7 @@ End Module"
Assert.Equal(
"Module1.M(Date d = #6/23/1912#)",
- GetName(source, "Module1.M", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, "#6/23/1912#"))
+ GetName(source, "Module1.M", DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types, argumentValues:={"#6/23/1912#"}))
End Sub
@@ -284,14 +329,120 @@ End Module"
GetName(source, "Module1.M2", DkmVariableInfoFlags.None))
End Sub
- Private Function GetName(source As String, methodName As String, argumentFlags As DkmVariableInfoFlags, ParamArray argumentValues() As String) As String
+
+ Sub GetReturnTypeNamePrimitive()
+ Dim source = "
+Class C
+ Function M1() As UInteger
+ Return 42
+ End Function
+End Class"
+
+ Assert.Equal("UInteger", GetReturnTypeName(source, "C.M1"))
+ End Sub
+
+
+ Sub GetReturnTypeNameNested()
+ Dim source = "
+Class C
+ Function M1() As N.D.E
+ Return Nothing
+ End Function
+End Class
+Namespace N
+ Class D
+ Friend Structure E
+ End Structure
+ End Class
+End Namespace"
+
+ Assert.Equal("N.D.E", GetReturnTypeName(source, "C.M1"))
+ End Sub
+
+
+ Sub GetReturnTypeNameGenericOfPrimitive()
+ Dim source = "
+Imports System
+Class C
+ Function M1() As Action(Of Int32)
+ Return Nothing
+ End Function
+End Class"
+
+ Assert.Equal("System.Action(Of Integer)", GetReturnTypeName(source, "C.M1"))
+ End Sub
+
+
+ Sub GetReturnTypeNameGenericOfNested()
+ Dim source = "
+Imports System
+Class C
+ Function M1() As Action(Of D)
+ Return Nothing
+ End Function
+ Class D
+ End Class
+End Class"
+
+ Assert.Equal("System.Action(Of C.D)", GetReturnTypeName(source, "C.M1"))
+ End Sub
+
+
+ Sub GetReturnTypeNameGenericOfGeneric()
+ Dim source = "
+Imports System
+Class C
+ Function M1(Of T)() As Action(Of Func(Of T))
+ Return Nothing
+ End Function
+End Class"
+
+ Assert.Equal("System.Action(Of System.Func(Of Object))", GetReturnTypeName(source, "C.M1", typeArguments:={GetType(Object)}))
+ End Sub
+
+ Private Function GetName(source As String, methodName As String, argumentFlags As DkmVariableInfoFlags, Optional typeArguments() As Type = Nothing, Optional argumentValues() As String = Nothing) As String
+ Dim serializedTypeArgumentNames = typeArguments?.Select(Function(t) t?.AssemblyQualifiedName).ToArray()
+ Return GetName(source, methodName, argumentFlags, serializedTypeArgumentNames, argumentValues)
+ End Function
+
+ Private Function GetName(source As String, methodName As String, argumentFlags As DkmVariableInfoFlags, typeArguments() As String, Optional argumentValues() As String = Nothing) As String
Debug.Assert((argumentFlags And (DkmVariableInfoFlags.Names Or DkmVariableInfoFlags.Types)) = argumentFlags,
"Unexpected argumentFlags", "argumentFlags = {0}", argumentFlags)
+ Dim instructionDecoder = VisualBasicInstructionDecoder.Instance
+ Dim method = GetConstructedMethod(source, methodName, typeArguments, instructionDecoder)
+
+ Dim includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types)
+ Dim includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names)
+ Dim builder As ArrayBuilder(Of String) = Nothing
+ If argumentValues IsNot Nothing Then
+ Assert.InRange(argumentValues.Length, 1, Integer.MaxValue)
+ builder = ArrayBuilder(Of String).GetInstance()
+ builder.AddRange(argumentValues)
+ End If
+
+ Dim name = instructionDecoder.GetName(method, includeParameterTypes, includeParameterNames, builder)
+ If builder IsNot Nothing Then
+ builder.Free()
+ End If
+
+ Return name
+ End Function
+
+ Private Function GetReturnTypeName(source As String, methodName As String, Optional typeArguments() As Type = Nothing) As String
+ Dim instructionDecoder = VisualBasicInstructionDecoder.Instance
+ Dim serializedTypeArgumentNames = typeArguments?.Select(Function(t) t?.AssemblyQualifiedName).ToArray()
+ Dim method = GetConstructedMethod(source, methodName, serializedTypeArgumentNames, instructionDecoder)
+
+ Return instructionDecoder.GetReturnTypeName(method)
+ End Function
+
+ Private Function GetConstructedMethod(source As String, methodName As String, serializedTypeArgumentNames() As String, instructionDecoder As VisualBasicInstructionDecoder) As MethodSymbol
Dim compilation = CreateCompilationWithReferences(
{VisualBasicSyntaxTree.ParseText(source)},
references:={MscorlibRef_v4_0_30316_17626, MsvbRef_v4_0_30319_17929},
- options:=TestOptions.DebugDll)
+ options:=TestOptions.DebugDll,
+ assemblyName:=NameOf(InstructionDecoderTests))
Dim runtime = CreateRuntimeInstance(compilation)
Dim moduleInstances = runtime.Modules
Dim blocks = moduleInstances.SelectAsArray(Function(m) m.MetadataBlock)
@@ -301,26 +452,24 @@ End Module"
' Once we have the method token, we want to look up the method (again)
' using the same helper as the product code. This helper will also map
' async/ iterator "MoveNext" methods to the original source method.
- Dim method = compilation.GetSourceMethod(
+ Dim method As MethodSymbol = compilation.GetSourceMethod(
DirectCast(frame.ContainingModule, PEModuleSymbol).Module.GetModuleVersionIdOrThrow(),
MetadataTokens.GetToken(frame.Handle))
- Dim includeParameterTypes = argumentFlags.Includes(DkmVariableInfoFlags.Types)
- Dim includeParameterNames = argumentFlags.Includes(DkmVariableInfoFlags.Names)
- Dim builder As ArrayBuilder(Of String) = Nothing
- If argumentValues.Length > 0 Then
- builder = ArrayBuilder(Of String).GetInstance()
- builder.AddRange(argumentValues)
- End If
-
- Dim frameDecoder = VisualBasicInstructionDecoder.Instance
- Dim frameName = frameDecoder.GetName(method, includeParameterTypes, includeParameterNames, builder)
- If builder IsNot Nothing Then
- builder.Free()
+ If serializedTypeArgumentNames IsNot Nothing Then
+ Assert.NotEmpty(serializedTypeArgumentNames)
+ Dim typeParameters = instructionDecoder.GetAllTypeParameters(method)
+ Assert.NotEmpty(typeParameters)
+ Dim typeNameDecoder = New EETypeNameDecoder(compilation, DirectCast(method.ContainingModule, PEModuleSymbol))
+ ' Use the same helper method as the FrameDecoder to get the TypeSymbols for the
+ ' generic type arguments (rather than using EETypeNameDecoder directly).
+ Dim typeArgumentSymbols = instructionDecoder.GetTypeSymbols(compilation, method, serializedTypeArgumentNames)
+ If Not typeArgumentSymbols.IsEmpty Then
+ method = instructionDecoder.ConstructMethod(method, typeParameters, typeArgumentSymbols)
+ End If
End If
- Return frameName
+ Return method
End Function
-
End Class
End Namespace
diff --git a/src/Roslyn.sln b/src/Roslyn.sln
index 3f18096f8fc4d..f74ff18e0d91e 100644
--- a/src/Roslyn.sln
+++ b/src/Roslyn.sln
@@ -285,6 +285,28 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Diagnostics", "Diagnostics"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetadataVisualizer", "Tools\Source\MetadataVisualizer\MetadataVisualizer.csproj", "{4C7847DB-C412-4D5E-B573-F12FA0A76127}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CodeAnalysis", "CodeAnalysis", "{2344BE45-7F6B-4A4E-9418-567FA2D9CA8C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysisDiagnosticAnalyzers", "Diagnostics\CodeAnalysis\Core\CodeAnalysisDiagnosticAnalyzers.csproj", "{D8762A0A-3832-47BE-BCF6-8B1060BE6B28}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpCodeAnalysisDiagnosticAnalyzers", "Diagnostics\CodeAnalysis\CSharp\CSharpCodeAnalysisDiagnosticAnalyzers.csproj", "{921B412A-5551-4853-82B4-46AD5A05A03E}"
+EndProject
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicCodeAnalysisDiagnosticAnalyzers", "Diagnostics\CodeAnalysis\VisualBasic\BasicCodeAnalysisDiagnosticAnalyzers.vbproj", "{B1A6A74B-E484-48FB-8745-7A30A06DB631}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysisDiagnosticAnalyzersTest", "Diagnostics\CodeAnalysis\Test\CodeAnalysisDiagnosticAnalyzersTest.csproj", "{0C2925AD-CD97-46FA-A686-E2C1AD19DAD8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysisDiagnosticsSetup", "Diagnostics\CodeAnalysis\Setup\CodeAnalysisDiagnosticsSetup.csproj", "{54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System.Runtime.Analyzers", "System.Runtime.Analyzers", "{F24D89AC-5A93-4F21-A329-DCEFD41EC0FE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemRuntimeAnalyzers", "Diagnostics\FxCop\System.Runtime.Analyzers\Core\SystemRuntimeAnalyzers.csproj", "{BAA0FEE4-93C8-46F0-BB36-53A6053776C8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpSystemRuntimeAnalyzers", "Diagnostics\FxCop\System.Runtime.Analyzers\CSharp\CSharpSystemRuntimeAnalyzers.csproj", "{A36451EC-1127-40CE-B841-47F393D24624}"
+EndProject
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicSystemRuntimeAnalyzers", "Diagnostics\FxCop\System.Runtime.Analyzers\VisualBasic\BasicSystemRuntimeAnalyzers.vbproj", "{D835C05E-9D83-40B2-9D25-19EB652F10D7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemRuntimeAnalyzersTest", "Diagnostics\FxCop\System.Runtime.Analyzers\Test\SystemRuntimeAnalyzersTest.csproj", "{0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{edc68a0e-c68d-4a74-91b7-bf38ec909888}*SharedItemsImports = 4
@@ -1246,6 +1268,60 @@ Global
{4C7847DB-C412-4D5E-B573-F12FA0A76127}.Release|Any CPU.Build.0 = Release|Any CPU
{4C7847DB-C412-4D5E-B573-F12FA0A76127}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{4C7847DB-C412-4D5E-B573-F12FA0A76127}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {D8762A0A-3832-47BE-BCF6-8B1060BE6B28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D8762A0A-3832-47BE-BCF6-8B1060BE6B28}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D8762A0A-3832-47BE-BCF6-8B1060BE6B28}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D8762A0A-3832-47BE-BCF6-8B1060BE6B28}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D8762A0A-3832-47BE-BCF6-8B1060BE6B28}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D8762A0A-3832-47BE-BCF6-8B1060BE6B28}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {921B412A-5551-4853-82B4-46AD5A05A03E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {921B412A-5551-4853-82B4-46AD5A05A03E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {921B412A-5551-4853-82B4-46AD5A05A03E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {921B412A-5551-4853-82B4-46AD5A05A03E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {921B412A-5551-4853-82B4-46AD5A05A03E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {921B412A-5551-4853-82B4-46AD5A05A03E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {B1A6A74B-E484-48FB-8745-7A30A06DB631}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B1A6A74B-E484-48FB-8745-7A30A06DB631}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {B1A6A74B-E484-48FB-8745-7A30A06DB631}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {B1A6A74B-E484-48FB-8745-7A30A06DB631}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B1A6A74B-E484-48FB-8745-7A30A06DB631}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B1A6A74B-E484-48FB-8745-7A30A06DB631}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {0C2925AD-CD97-46FA-A686-E2C1AD19DAD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C2925AD-CD97-46FA-A686-E2C1AD19DAD8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0C2925AD-CD97-46FA-A686-E2C1AD19DAD8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0C2925AD-CD97-46FA-A686-E2C1AD19DAD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C2925AD-CD97-46FA-A686-E2C1AD19DAD8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {0C2925AD-CD97-46FA-A686-E2C1AD19DAD8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {A36451EC-1127-40CE-B841-47F393D24624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A36451EC-1127-40CE-B841-47F393D24624}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {A36451EC-1127-40CE-B841-47F393D24624}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {A36451EC-1127-40CE-B841-47F393D24624}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A36451EC-1127-40CE-B841-47F393D24624}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {A36451EC-1127-40CE-B841-47F393D24624}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863}.Release|Mixed Platforms.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1375,6 +1451,16 @@ Global
{5002636A-FE8D-40BF-8818-AB513A2194FA} = {235A3418-A3B0-4844-BCEB-F1CF45069232}
{ABDBAC1E-350E-4DC3-BB45-3504404545EE} = {235A3418-A3B0-4844-BCEB-F1CF45069232}
{BEDC5A4A-809E-4017-9CFD-6C8D4E1847F0} = {235A3418-A3B0-4844-BCEB-F1CF45069232}
- {4C7847DB-C412-4D5E-B573-F12FA0A76127} = {64BDF58B-41BA-A19E-0D34-B5FA598403B6}
+ {2344BE45-7F6B-4A4E-9418-567FA2D9CA8C} = {5F5DD61A-746D-40AE-A89C-EF82B39C036E}
+ {D8762A0A-3832-47BE-BCF6-8B1060BE6B28} = {2344BE45-7F6B-4A4E-9418-567FA2D9CA8C}
+ {921B412A-5551-4853-82B4-46AD5A05A03E} = {2344BE45-7F6B-4A4E-9418-567FA2D9CA8C}
+ {B1A6A74B-E484-48FB-8745-7A30A06DB631} = {2344BE45-7F6B-4A4E-9418-567FA2D9CA8C}
+ {0C2925AD-CD97-46FA-A686-E2C1AD19DAD8} = {2344BE45-7F6B-4A4E-9418-567FA2D9CA8C}
+ {54F6AE18-B0CD-4799-9DF0-9B1AAD6A78AF} = {2344BE45-7F6B-4A4E-9418-567FA2D9CA8C}
+ {F24D89AC-5A93-4F21-A329-DCEFD41EC0FE} = {24E8CBFA-38D2-486F-B772-C10AB2DC7F01}
+ {BAA0FEE4-93C8-46F0-BB36-53A6053776C8} = {F24D89AC-5A93-4F21-A329-DCEFD41EC0FE}
+ {A36451EC-1127-40CE-B841-47F393D24624} = {F24D89AC-5A93-4F21-A329-DCEFD41EC0FE}
+ {D835C05E-9D83-40B2-9D25-19EB652F10D7} = {F24D89AC-5A93-4F21-A329-DCEFD41EC0FE}
+ {0FAE8CB3-4D2F-4A11-B1E6-F47EFF0FB863} = {F24D89AC-5A93-4F21-A329-DCEFD41EC0FE}
EndGlobalSection
EndGlobal
diff --git a/src/Test/PdbUtilities/Metadata/MetadataReaderPdbExtensions.cs b/src/Test/PdbUtilities/Metadata/MetadataReaderPdbExtensions.cs
index 5eed315af4f8c..7bf8727f158bb 100644
--- a/src/Test/PdbUtilities/Metadata/MetadataReaderPdbExtensions.cs
+++ b/src/Test/PdbUtilities/Metadata/MetadataReaderPdbExtensions.cs
@@ -4,9 +4,11 @@
using System.Diagnostics;
using System.Reflection.Metadata.Ecma335;
+// TODO: to be moved to System.Reflection.Metadata.
+
namespace System.Reflection.Metadata
{
- public enum ImportScopeKind
+ internal enum ImportScopeKind
{
ImportNamespace = 1,
ImportAssemblyNamespace = 2,
@@ -19,7 +21,7 @@ public enum ImportScopeKind
AliasType = 9
}
- public struct ImportDefinition
+ internal struct ImportDefinition
{
private readonly ImportScopeKind _kind;
private readonly BlobHandle _alias;
@@ -28,8 +30,8 @@ public struct ImportDefinition
internal ImportDefinition(
ImportScopeKind kind,
- BlobHandle alias = default(BlobHandle),
- AssemblyReferenceHandle assembly = default(AssemblyReferenceHandle),
+ BlobHandle alias = default(BlobHandle),
+ AssemblyReferenceHandle assembly = default(AssemblyReferenceHandle),
Handle typeOrNamespace = default(Handle))
{
Debug.Assert(
diff --git a/src/Tools/Source/RunTests/TestRunner.cs b/src/Tools/Source/RunTests/TestRunner.cs
index b18c3c0a65752..48b64d223ce33 100644
--- a/src/Tools/Source/RunTests/TestRunner.cs
+++ b/src/Tools/Source/RunTests/TestRunner.cs
@@ -129,8 +129,8 @@ private async Task RunTest(string assemblyPath)
var all = File.ReadAllText(resultsPath).Trim();
if (all.Length == 0)
{
- var output = processOutput.OutputLines.Concat(processOutput.ErrorLines).Aggregate((x, y) => x + Environment.NewLine + y);
- File.WriteAllText(resultsPath, output);
+ var output = processOutput.OutputLines.Concat(processOutput.ErrorLines).ToArray();
+ File.WriteAllLines(resultsPath, output);
}
errorOutput = processOutput.ErrorLines.Aggregate((x, y) => x + Environment.NewLine + y);
diff --git a/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs b/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs
index d84ea05d3c586..c24f3bca84032 100644
--- a/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs
+++ b/src/Workspaces/Core/Portable/Editing/SyntaxEditorExtensions.cs
@@ -94,12 +94,12 @@ public static void InsertMembers(this SyntaxEditor editor, SyntaxNode declaratio
public static void AddInterfaceType(this SyntaxEditor editor, SyntaxNode declaration, SyntaxNode interfaceType)
{
- editor.ReplaceNode(declaration, (d, g) => g.AddInterfaceType(declaration, interfaceType));
+ editor.ReplaceNode(declaration, (d, g) => g.AddInterfaceType(d, interfaceType));
}
public static void AddBaseType(this SyntaxEditor editor, SyntaxNode declaration, SyntaxNode baseType)
{
- editor.ReplaceNode(declaration, (d, g) => g.AddBaseType(declaration, baseType));
+ editor.ReplaceNode(declaration, (d, g) => g.AddBaseType(d, baseType));
}
}
}
diff --git a/src/Workspaces/Core/Portable/Shared/Utilities/CommonFormattingHelpers.cs b/src/Workspaces/Core/Portable/Shared/Utilities/CommonFormattingHelpers.cs
index d3af0c3551fce..cd6ca2f63b19c 100644
--- a/src/Workspaces/Core/Portable/Shared/Utilities/CommonFormattingHelpers.cs
+++ b/src/Workspaces/Core/Portable/Shared/Utilities/CommonFormattingHelpers.cs
@@ -149,36 +149,6 @@ public static int GetTokenColumn(this SyntaxTree tree, SyntaxToken token, int ta
return line.GetColumnFromLineOffset(startPosition - line.Start, tabSize);
}
- public static bool IsFirstTokenOnLine(this SyntaxTree tree, SyntaxToken token)
- {
- Contract.ThrowIfNull(tree);
- Contract.ThrowIfTrue(token.RawKind == 0);
-
- var previousToken = token.GetPreviousToken();
-
- // there should be only whitespace between two tokens unless the token can't be the first token on line
- if (!string.IsNullOrWhiteSpace(tree.GetText().GetText(previousToken, token)))
- {
- return false;
- }
-
- if (previousToken.RawKind == 0)
- {
- return true;
- }
-
- var previousLine = tree.GetText().Lines.GetLineFromPosition(previousToken.Span.End);
- var lineNumber = tree.GetText().Lines.IndexOf(token.SpanStart);
-
- // if span.End is at the edge of two lines, it belongs to previous line
- if (previousLine.Start == previousToken.Span.End)
- {
- return previousLine.LineNumber - 1 < lineNumber;
- }
-
- return previousLine.LineNumber < lineNumber;
- }
-
public static string GetText(this SourceText text, SyntaxToken token1, SyntaxToken token2)
{
return (token1.RawKind == 0) ? text.ToString(TextSpan.FromBounds(0, token2.SpanStart)) : text.ToString(TextSpan.FromBounds(token1.Span.End, token2.SpanStart));
diff --git a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb
index ca58e72f1268f..db3d379a3e793 100644
--- a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb
+++ b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb
@@ -880,8 +880,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
name = moduleDecl.ModuleStatement.Identifier.ValueText
typeParameterList = moduleDecl.ModuleStatement.TypeParameterList
Case SyntaxKind.NamespaceBlock
- Return GetNodeName(CType(node, NamespaceBlockSyntax).NamespaceStatement.Name, includeTypeParameters:=False)
- typeParameterList = Nothing
+ Dim nameSyntax = CType(node, NamespaceBlockSyntax).NamespaceStatement.Name
+ If nameSyntax.Kind() = SyntaxKind.GlobalName Then
+ Return Nothing
+ Else
+ Return GetNodeName(nameSyntax, includeTypeParameters:=False)
+ End If
Case SyntaxKind.QualifiedName
Dim qualified = CType(node, QualifiedNameSyntax)
If qualified.Left.Kind() = SyntaxKind.GlobalName Then