forked from dotnet/roslyn
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move Expression Evaluator to Open (changeset 1411117)
- Loading branch information
1 parent
ccb1afd
commit 6f53207
Showing
327 changed files
with
180,121 additions
and
0 deletions.
There are no files selected for viewing
69 changes: 69 additions & 0 deletions
69
src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Binders/EEMethodBinder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// 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.Generic; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using Microsoft.CodeAnalysis.CSharp.Symbols; | ||
using Roslyn.Utilities; | ||
|
||
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator | ||
{ | ||
internal sealed class EEMethodBinder : Binder | ||
{ | ||
private readonly MethodSymbol _containingMethod; | ||
private readonly int _parameterOffset; | ||
private readonly ImmutableArray<ParameterSymbol> _targetParameters; | ||
private readonly Binder _sourceBinder; | ||
|
||
internal EEMethodBinder(EEMethodSymbol method, MethodSymbol containingMethod, Binder next) : base(next) | ||
{ | ||
// There are a lot of method symbols floating around and we're doing some subtle things with them. | ||
// 1) method is the EEMethodSymbol that we're going to synthesize and hand to the debugger to evaluate. | ||
// 2) containingMethod is the method that we are conceptually in, e.g. the method containing the | ||
// lambda that is on top of the call stack. Any type parameters will have been replaced with the | ||
// corresponding type parameters from (1) and its containing type. | ||
// 3) method.SubstitutedSourceMethod is the method that we are actually in, e.g. a lambda method in | ||
// a display class. Any type parameters will have been replaced with the corresponding type parameters | ||
// from (1). | ||
// So why do we need all these methods? | ||
// 1) gives us the parameters that we need to actually bind to (it's no good to bind to the symbols | ||
// owned by (2) or (3)). Also, it happens to contain (3), so we don't need to pass (3) explicitly. | ||
// 2) is where we want to pretend we're binding expressions, so we make it the containing symbol of | ||
// this binder. | ||
// 3) is where we'll pretend to be for the purposes of looking up parameters by name. However, any | ||
// parameters we bind to from (3) will be replaced by the corresponding parameters from (1). | ||
|
||
_containingMethod = containingMethod; | ||
var substitutedSourceMethod = method.SubstitutedSourceMethod; | ||
_parameterOffset = substitutedSourceMethod.IsStatic ? 0 : 1; | ||
_targetParameters = method.Parameters; | ||
_sourceBinder = new InMethodBinder(substitutedSourceMethod, new BuckStopsHereBinder(next.Compilation)); | ||
} | ||
|
||
internal override void LookupSymbolsInSingleBinder(LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics) | ||
{ | ||
_sourceBinder.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteDiagnostics); | ||
|
||
var symbols = result.Symbols; | ||
for (int i = 0; i < symbols.Count; i++) | ||
{ | ||
// Type parameters requiring mapping to the target type and | ||
// should be found by WithMethodTypeParametersBinder instead. | ||
var parameter = (ParameterSymbol)symbols[i]; | ||
Debug.Assert(parameter.ContainingSymbol == _sourceBinder.ContainingMemberOrLambda); | ||
symbols[i] = _targetParameters[parameter.Ordinal + _parameterOffset]; | ||
} | ||
} | ||
|
||
protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo info, LookupOptions options, Binder originalBinder) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
internal override Symbol ContainingMemberOrLambda | ||
{ | ||
get { return _containingMethod; } | ||
} | ||
} | ||
} |
133 changes: 133 additions & 0 deletions
133
src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Binders/PlaceholderLocalBinder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// 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.Generic; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using System.Globalization; | ||
using Microsoft.CodeAnalysis.CSharp.Symbols; | ||
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.ExpressionEvaluator; | ||
using Roslyn.Utilities; | ||
|
||
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator | ||
{ | ||
internal sealed class PlaceholderLocalBinder : LocalScopeBinder | ||
{ | ||
private readonly InspectionContext _inspectionContext; | ||
private readonly TypeNameDecoder<PEModuleSymbol, TypeSymbol> _typeNameDecoder; | ||
private readonly CSharpSyntaxNode _syntax; | ||
private readonly MethodSymbol _containingMethod; | ||
|
||
internal PlaceholderLocalBinder( | ||
InspectionContext inspectionContext, | ||
TypeNameDecoder<PEModuleSymbol, TypeSymbol> typeNameDecoder, | ||
CSharpSyntaxNode syntax, | ||
MethodSymbol containingMethod, | ||
Binder next) : | ||
base(next) | ||
{ | ||
_inspectionContext = inspectionContext; | ||
_typeNameDecoder = typeNameDecoder; | ||
_syntax = syntax; | ||
_containingMethod = containingMethod; | ||
} | ||
|
||
internal sealed override void LookupSymbolsInSingleBinder( | ||
LookupResult result, | ||
string name, | ||
int arity, | ||
ConsList<Symbol> basesBeingResolved, | ||
LookupOptions options, | ||
Binder originalBinder, | ||
bool diagnose, | ||
ref HashSet<DiagnosticInfo> useSiteDiagnostics) | ||
{ | ||
if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.NamespacesOrTypesOnly | LookupOptions.LabelsOnly)) != 0) | ||
{ | ||
return; | ||
} | ||
|
||
var local = this.LookupPlaceholder(name); | ||
if ((object)local == null) | ||
{ | ||
base.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics); | ||
} | ||
else | ||
{ | ||
result.MergeEqual(this.CheckViability(local, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved)); | ||
} | ||
} | ||
|
||
protected sealed override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo info, LookupOptions options, Binder originalBinder) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
protected override ImmutableArray<LocalSymbol> BuildLocals() | ||
{ | ||
var builder = ArrayBuilder<LocalSymbol>.GetInstance(); | ||
var declaration = _syntax as LocalDeclarationStatementSyntax; | ||
if (declaration != null) | ||
{ | ||
var kind = declaration.IsConst ? LocalDeclarationKind.Constant : LocalDeclarationKind.RegularVariable; | ||
foreach (var variable in declaration.Declaration.Variables) | ||
{ | ||
var local = SourceLocalSymbol.MakeLocal(_containingMethod, this, declaration.Declaration.Type, variable.Identifier, kind, variable.Initializer); | ||
builder.Add(local); | ||
} | ||
} | ||
return builder.ToImmutableAndFree(); | ||
} | ||
|
||
private PlaceholderLocalSymbol LookupPlaceholder(string name) | ||
{ | ||
if (name.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
var valueText = name.Substring(2); | ||
ulong address; | ||
if (!ulong.TryParse(valueText, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out address)) | ||
{ | ||
// Invalid value should have been caught by Lexer. | ||
throw ExceptionUtilities.UnexpectedValue(valueText); | ||
} | ||
return new ObjectAddressLocalSymbol(_containingMethod, name, this.Compilation.GetSpecialType(SpecialType.System_Object), address); | ||
} | ||
|
||
PseudoVariableKind kind; | ||
string id; | ||
int index; | ||
if (!PseudoVariableUtilities.TryParseVariableName(name, caseSensitive: true, kind: out kind, id: out id, index: out index)) | ||
{ | ||
return null; | ||
} | ||
|
||
var typeName = PseudoVariableUtilities.GetTypeName(_inspectionContext, kind, id, index); | ||
if (typeName == null) | ||
{ | ||
return null; | ||
} | ||
|
||
Debug.Assert(typeName.Length > 0); | ||
|
||
var type = _typeNameDecoder.GetTypeSymbolForSerializedType(typeName); | ||
Debug.Assert((object)type != null); | ||
|
||
switch (kind) | ||
{ | ||
case PseudoVariableKind.Exception: | ||
case PseudoVariableKind.StowedException: | ||
return new ExceptionLocalSymbol(_containingMethod, id, type); | ||
case PseudoVariableKind.ReturnValue: | ||
return new ReturnValueLocalSymbol(_containingMethod, id, type, index); | ||
case PseudoVariableKind.ObjectId: | ||
return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: false); | ||
case PseudoVariableKind.DeclaredLocal: | ||
return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: true); | ||
default: | ||
throw ExceptionUtilities.UnexpectedValue(kind); | ||
} | ||
} | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Binders/WithTypeArgumentsBinder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// 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.CSharp.Symbols; | ||
using Roslyn.Utilities; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Threading; | ||
|
||
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator | ||
{ | ||
internal sealed class WithTypeArgumentsBinder : WithTypeParametersBinder | ||
{ | ||
private readonly ImmutableArray<TypeSymbol> _typeArguments; | ||
private MultiDictionary<string, TypeParameterSymbol> _lazyTypeParameterMap; | ||
|
||
internal WithTypeArgumentsBinder(ImmutableArray<TypeSymbol> typeArguments, Binder next) | ||
: base(next) | ||
{ | ||
Debug.Assert(!typeArguments.IsDefaultOrEmpty); | ||
Debug.Assert(typeArguments.All(ta => ta.Kind == SymbolKind.TypeParameter)); | ||
_typeArguments = typeArguments; | ||
} | ||
|
||
protected override MultiDictionary<string, TypeParameterSymbol> TypeParameterMap | ||
{ | ||
get | ||
{ | ||
if (_lazyTypeParameterMap == null) | ||
{ | ||
var result = new MultiDictionary<string, TypeParameterSymbol>(); | ||
foreach (TypeParameterSymbol tps in _typeArguments) | ||
{ | ||
result.Add(tps.Name, tps); | ||
} | ||
Interlocked.CompareExchange(ref _lazyTypeParameterMap, result, null); | ||
} | ||
return _lazyTypeParameterMap; | ||
} | ||
} | ||
|
||
protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo result, LookupOptions options, Binder originalBinder) | ||
{ | ||
if (CanConsiderTypeParameters(options)) | ||
{ | ||
foreach (var parameter in _typeArguments) | ||
{ | ||
if (originalBinder.CanAddLookupSymbolInfo(parameter, options, null)) | ||
{ | ||
result.AddSymbol(parameter, parameter.Name, 0); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/CSharpExpressionCompiler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics; | ||
using Microsoft.CodeAnalysis.ExpressionEvaluator; | ||
using Microsoft.VisualStudio.Debugger; | ||
using Microsoft.VisualStudio.Debugger.Clr; | ||
using Microsoft.VisualStudio.Debugger.Evaluation; | ||
|
||
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator | ||
{ | ||
[DkmReportNonFatalWatsonException(ExcludeExceptionType = typeof(NotImplementedException)), DkmContinueCorruptingException] | ||
internal sealed class CSharpExpressionCompiler : ExpressionCompiler | ||
{ | ||
private static readonly DkmCompilerId s_compilerId = new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.CSharp); | ||
|
||
internal override DiagnosticFormatter DiagnosticFormatter | ||
{ | ||
get { return DiagnosticFormatter.Instance; } | ||
} | ||
|
||
internal override DkmCompilerId CompilerId | ||
{ | ||
get { return s_compilerId; } | ||
} | ||
|
||
internal override EvaluationContextBase CreateTypeContext( | ||
DkmClrAppDomain appDomain, | ||
ImmutableArray<MetadataBlock> metadataBlocks, | ||
Guid moduleVersionId, | ||
int typeToken) | ||
{ | ||
var previous = appDomain.GetDataItem<CSharpMetadataContext>(); | ||
var context = EvaluationContext.CreateTypeContext( | ||
appDomain.GetDataItem<CSharpMetadataContext>(), | ||
metadataBlocks, | ||
moduleVersionId, | ||
typeToken); | ||
|
||
// New type context is not attached to the AppDomain since it is less | ||
// re-usable than the previous attached method context. (We could hold | ||
// on to it if we don't have a previous method context but it's unlikely | ||
// that we evaluated a type-level expression before a method-level.) | ||
Debug.Assert(previous == null || context != previous.EvaluationContext); | ||
|
||
return context; | ||
} | ||
|
||
internal override EvaluationContextBase CreateMethodContext( | ||
DkmClrAppDomain appDomain, | ||
ImmutableArray<MetadataBlock> metadataBlocks, | ||
Lazy<ImmutableArray<AssemblyReaders>> unusedLazyAssemblyReaders, | ||
object symReader, | ||
Guid moduleVersionId, | ||
int methodToken, | ||
int methodVersion, | ||
int ilOffset, | ||
int localSignatureToken) | ||
{ | ||
var previous = appDomain.GetDataItem<CSharpMetadataContext>(); | ||
var context = EvaluationContext.CreateMethodContext( | ||
previous, | ||
metadataBlocks, | ||
symReader, | ||
moduleVersionId, | ||
methodToken, | ||
methodVersion, | ||
ilOffset, | ||
localSignatureToken); | ||
|
||
if (previous == null || context != previous.EvaluationContext) | ||
{ | ||
appDomain.SetDataItem(DkmDataCreationDisposition.CreateAlways, new CSharpMetadataContext(context)); | ||
} | ||
|
||
return context; | ||
} | ||
|
||
internal override bool RemoveDataItem(DkmClrAppDomain appDomain) | ||
{ | ||
return appDomain.RemoveDataItem<CSharpMetadataContext>(); | ||
} | ||
} | ||
} |
Oops, something went wrong.