File: Compilation\SemanticModelAPITests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Symbol\Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    public class SemanticTests : CSharpTestBase
    {
        [Fact]
        public void PatternIndexAndRangeIndexersSpeculativeModel()
        {
            var comp = CreateCompilationWithIndexAndRange(@"
class C
{
    int Length => 0;
    int this[int i] => i;
    char Slice(int i, int j) => 'a';
    void M()
    {
        _ = this[^0];
        _ = this[0..];
    }              
}");
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees[0];
            var model = comp.GetSemanticModel(tree);
            var root = tree.GetRoot();
            var m = root.DescendantNodes().OfType<MethodDeclarationSyntax>().Single(decl => decl.Identifier.ValueText == "M");
            var m2 = m.WithoutTrailingTrivia();
 
            var accesses = m.DescendantNodes().OfType<ElementAccessExpressionSyntax>().ToList();
            var indexerAccess = accesses[0];
 
            model.TryGetSpeculativeSemanticModelForMethodBody(indexerAccess.SpanStart, m2, out var speculativeModel);
 
            accesses = m2.DescendantNodes().OfType<ElementAccessExpressionSyntax>().ToList();
            indexerAccess = accesses[0];
 
            var typeInfo = speculativeModel.GetTypeInfo(indexerAccess);
            Assert.Equal(SpecialType.System_Int32, typeInfo.Type.SpecialType);
 
            indexerAccess = accesses[1];
            typeInfo = speculativeModel.GetTypeInfo(indexerAccess);
            Assert.Equal(SpecialType.System_Char, typeInfo.Type.SpecialType);
        }
 
        [Fact]
        public void UnmanagedConstraintOnExtensionMethod()
        {
            var src = @"
public static class Ext
{
    public static T GenericExtension<T>(ref this T self) where T : unmanaged
    {
        return self;
    }
}
";
            var src2 = @"
public class Program
{
    public struct S<T> where T : unmanaged
    {
        public T t;
    }
 
    static void M<T>(S<T> s) where T : unmanaged
    {
        s.GenericExtension();
    }
}";
            var comp1 = CreateCompilation(src, parseOptions: TestOptions.Regular8);
 
            var comp2 = CreateCompilation(src2, parseOptions: TestOptions.Regular8,
                references: new[] { comp1.ToMetadataReference() });
            comp2.VerifyDiagnostics();
            Assert.NotNull(checkSymbolInfo(comp2).Symbol);
 
            comp2 = CreateCompilation(src2, parseOptions: TestOptions.Regular7_3,
                references: new[] { comp1.ToMetadataReference() });
            comp2.VerifyDiagnostics(
                // (11,11): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater.
                //         s.GenericExtension();
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "GenericExtension").WithArguments("unmanaged constructed types", "8.0").WithLocation(11, 11));
 
            var info = checkSymbolInfo(comp2);
            Assert.Null(info.Symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason);
 
            static SymbolInfo checkSymbolInfo(CSharpCompilation comp)
            {
                SyntaxTree tree = comp.SyntaxTrees[0];
                var model = comp.GetSemanticModel(tree);
                SyntaxNode root = tree.GetRoot();
                var invoke = root.DescendantNodes().OfType<MemberAccessExpressionSyntax>()
                    .Where(e => e.Name.ToString() == "GenericExtension").First();
 
                return model.GetSymbolInfo(invoke);
            }
        }
 
        [Fact]
        public void PatternIndexAndRangeIndexers()
        {
            var comp = CreateCompilationWithIndexAndRange(@"
class C
{
    int Length => 0;
    int this[int i] => i;
    char Slice(int i, int j) => 'a';
    void M()
    {
        _ = this[^0];
        _ = this[0..];
    }
}");
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees[0];
            var model = comp.GetSemanticModel(tree);
            var root = tree.GetCompilationUnitRoot();
 
            var accesses = root.DescendantNodes().OfType<ElementAccessExpressionSyntax>().ToList();
            var indexerAccess = accesses[0];
 
            var typeInfo = model.GetTypeInfo(indexerAccess);
            Assert.Equal(SpecialType.System_Int32, typeInfo.Type.SpecialType);
            var symbolInfo = model.GetSymbolInfo(indexerAccess);
            var propertySymbol = (IPropertySymbol)symbolInfo.Symbol;
            Assert.NotNull(symbolInfo.Symbol);
            Assert.True(propertySymbol.IsIndexer);
            Assert.Empty(symbolInfo.CandidateSymbols);
 
            indexerAccess = accesses[1];
 
            typeInfo = model.GetTypeInfo(indexerAccess);
            Assert.Equal(SpecialType.System_Char, typeInfo.Type.SpecialType);
            symbolInfo = model.GetSymbolInfo(indexerAccess);
            Assert.NotNull(symbolInfo.Symbol);
            Assert.Equal(SymbolKind.Method, symbolInfo.Symbol.Kind);
            Assert.Equal("Slice", symbolInfo.Symbol.Name);
            Assert.Empty(symbolInfo.CandidateSymbols);
        }
 
        [Fact]
        public void RefReassignSymbolInfo()
        {
            var comp = CreateCompilation(@"
class C
{
    int f = 0; 
    void M(ref int rx)
    {
        (rx = ref f) = 0;
    }
}");
            comp.VerifyDiagnostics();
            var tree = comp.SyntaxTrees.Single();
            var root = tree.GetCompilationUnitRoot();
            var assignment = root.DescendantNodes().OfType<ParenthesizedExpressionSyntax>().Single();
            var model = comp.GetSemanticModel(tree);
            Assert.Null(model.GetDeclaredSymbol(assignment));
            var assignmentInfo = model.GetSymbolInfo(assignment);
            Assert.Null(assignmentInfo.Symbol);
        }
 
        [Fact]
        public void RefForSymbolInfo()
        {
            var comp = CreateCompilation(@"
class C
{
    void M(int x)
    {
        for (ref readonly int rx = ref x;;)
        {
            if (rx == 0)
            {
                return;
            }
        }
    }
}");
            comp.VerifyDiagnostics();
            var tree = comp.SyntaxTrees.Single();
            var root = tree.GetCompilationUnitRoot();
            var rx = root.DescendantNodes().OfType<IdentifierNameSyntax>().Last();
            var model = comp.GetSemanticModel(tree);
            var rxInfo = model.GetSymbolInfo(rx);
            Assert.NotNull(rxInfo.Symbol);
            var rxSymbol = Assert.IsAssignableFrom<ILocalSymbol>(rxInfo.Symbol);
            Assert.True(rxSymbol.IsRef);
            Assert.Equal(RefKind.RefReadOnly, rxSymbol.RefKind);
            var rxDecl = root.DescendantNodes().OfType<ForStatementSyntax>().Single().Declaration;
            Assert.Same(model.GetDeclaredSymbol(rxDecl.Variables.Single()), rxSymbol);
        }
 
        [Fact]
        public void RefForEachSymbolInfo()
        {
            var comp = CreateCompilationWithMscorlibAndSpan(@"
using System;
class C
{
    void M(Span<int> span)
    {
        foreach (ref readonly int rx in span)
        {
            if (rx == 0)
            {
                return;
            }
        }
    }
}");
            comp.VerifyDiagnostics();
            var tree = comp.SyntaxTrees.Single();
            var root = tree.GetCompilationUnitRoot();
            var rx = root.DescendantNodes().OfType<IdentifierNameSyntax>().Last();
            var model = comp.GetSemanticModel(tree);
            var rxInfo = model.GetSymbolInfo(rx);
            Assert.NotNull(rxInfo.Symbol);
            var rxSymbol = Assert.IsAssignableFrom<ILocalSymbol>(rxInfo.Symbol);
            Assert.True(rxSymbol.IsRef);
            Assert.Equal(RefKind.RefReadOnly, rxSymbol.RefKind);
            var rxDecl = root.DescendantNodes().OfType<ForEachStatementSyntax>().Single();
            Assert.Same(model.GetDeclaredSymbol(rxDecl), rxSymbol);
        }
 
        [Fact]
        public void LocalSymbolsAreEquivalentAcrossSemanticModelsFromTheSameCompilation()
        {
            var text = @"public class C { public void M() { int x = 10; } }";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
 
            var model1 = comp.GetSemanticModel(tree);
            var model2 = comp.GetSemanticModel(tree);
            Assert.NotEqual(model1, model2);
 
            var vardecl = tree.GetCompilationUnitRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().First();
            var symbol1 = model1.GetDeclaredSymbol(vardecl);
            var symbol2 = model2.GetDeclaredSymbol(vardecl);
 
            Assert.NotSame(symbol1, symbol2);
            Assert.Equal(symbol1, symbol2);
        }
 
        [Fact]
        public void LocalSymbolsAreDifferentAcrossSemanticModelsFromDifferentCompilations()
        {
            var text = @"public class C { public void M() { int x = 10; } }";
            var tree = Parse(text);
            var comp1 = CreateCompilation(tree);
            var comp2 = CreateCompilation(tree);
 
            var model1 = comp1.GetSemanticModel(tree);
            var model2 = comp2.GetSemanticModel(tree);
            Assert.NotEqual(model1, model2);
 
            var vardecl = tree.GetCompilationUnitRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().First();
            var symbol1 = model1.GetDeclaredSymbol(vardecl);
            var symbol2 = model2.GetDeclaredSymbol(vardecl);
 
            Assert.NotSame(symbol1, symbol2);
            Assert.NotEqual(symbol1, symbol2);
        }
 
        [Fact]
        public void RangeVariableSymbolsAreEquivalentAcrossSemanticModelsFromTheSameCompilation()
        {
            var text = @"using System.Linq; public class C { public void M() { var q = from c in string.Empty select c; } }";
            var tree = Parse(text);
            var comp = CreateCompilationWithMscorlib40AndSystemCore(new[] { tree });
 
            var model1 = comp.GetSemanticModel(tree);
            var model2 = comp.GetSemanticModel(tree);
            Assert.NotEqual(model1, model2);
 
            var vardecl = tree.GetCompilationUnitRoot().DescendantNodes().OfType<QueryClauseSyntax>().First();
            var symbol1 = model1.GetDeclaredSymbol(vardecl);
            var symbol2 = model2.GetDeclaredSymbol(vardecl);
 
            Assert.NotSame(symbol1, symbol2);
            Assert.Equal(symbol1, symbol2);
        }
 
        [Fact]
        public void RangeVariableSymbolsAreDifferentAcrossSemanticModelsFromDifferentCompilations()
        {
            var text = @"using System.Linq; public class C { public void M() { var q = from c in string.Empty select c; } }";
            var tree = Parse(text);
            var comp1 = CreateCompilationWithMscorlib40AndSystemCore(new[] { tree });
            var comp2 = CreateCompilationWithMscorlib40AndSystemCore(new[] { tree });
 
            var model1 = comp1.GetSemanticModel(tree);
            var model2 = comp2.GetSemanticModel(tree);
            Assert.NotEqual(model1, model2);
 
            var vardecl = tree.GetCompilationUnitRoot().DescendantNodes().OfType<QueryClauseSyntax>().First();
            var symbol1 = model1.GetDeclaredSymbol(vardecl);
            var symbol2 = model2.GetDeclaredSymbol(vardecl);
 
            Assert.NotSame(symbol1, symbol2);
            Assert.NotEqual(symbol1, symbol2);
        }
 
        [Fact]
        public void LabelSymbolsAreEquivalentAcrossSemanticModelsFromSameCompilation()
        {
            var text = @"public class C { public void M() { label: goto label; } }";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
 
            var model1 = comp.GetSemanticModel(tree);
            var model2 = comp.GetSemanticModel(tree);
            Assert.NotEqual(model1, model2);
 
            var statement = tree.GetCompilationUnitRoot().DescendantNodes().OfType<GotoStatementSyntax>().First();
            var symbol1 = model1.GetSymbolInfo(statement.Expression).Symbol;
            var symbol2 = model2.GetSymbolInfo(statement.Expression).Symbol;
 
            Assert.False(ReferenceEquals(symbol1, symbol2));
            Assert.Equal(symbol1, symbol2);
        }
 
        [Fact]
        public void LambdaParameterSymbolsAreEquivalentAcrossSemanticModelsFromSameCompilation()
        {
            var text = @"using System; public class C { public void M() { Func<int,int> f = (p) => p; } }";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
 
            var model1 = comp.GetSemanticModel(tree);
            var model2 = comp.GetSemanticModel(tree);
            Assert.NotEqual(model1, model2);
 
            var paramdecl = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().First();
            var symbol1 = model1.GetDeclaredSymbol(paramdecl);
            var symbol2 = model2.GetDeclaredSymbol(paramdecl);
 
            Assert.NotSame(symbol1, symbol2);
            Assert.Equal(symbol1.ContainingSymbol, symbol2.ContainingSymbol);
            Assert.Equal(symbol1, symbol2);
        }
 
        [Fact]
        public void LambdaParameterSymbolsAreDifferentAcrossSemanticModelsFromDifferentCompilations()
        {
            var text = @"using System; public class C { public void M() { Func<int,int> f = (p) => p; } }";
            var tree1 = Parse(text);
            var tree2 = Parse(text);
            var comp1 = CreateCompilation(tree1);
            var comp2 = CreateCompilation(tree2);
 
            var model1 = comp1.GetSemanticModel(tree1);
            var model2 = comp2.GetSemanticModel(tree2);
            Assert.NotEqual(model1, model2);
 
            var paramdecl1 = tree1.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().First();
            var symbol1 = model1.GetDeclaredSymbol(paramdecl1);
            var paramdecl2 = tree2.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().First();
            var symbol2 = model2.GetDeclaredSymbol(paramdecl2);
 
            Assert.NotSame(symbol1, symbol2);
            Assert.NotEqual(symbol1.ContainingSymbol, symbol2.ContainingSymbol);
            Assert.NotEqual(symbol1, symbol2);
        }
 
        [WorkItem(539740, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539740")]
        [Fact]
        public void NamespaceWithoutName()
        {
            var text = "namespace";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            comp.VerifyDiagnostics(
                // (1,10): error CS1001: Identifier expected
                // namespace
                Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 10),
                // (1,10): error CS1514: { expected
                // namespace
                Diagnostic(ErrorCode.ERR_LbraceExpected, "").WithLocation(1, 10),
                // (1,10): error CS1513: } expected
                // namespace
                Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(1, 10));
 
            var nsArray = tree.GetCompilationUnitRoot().DescendantNodes().Where(node => node.IsKind(SyntaxKind.NamespaceDeclaration)).ToArray();
            Assert.Equal(1, nsArray.Length);
 
            var nsSyntax = nsArray[0] as NamespaceDeclarationSyntax;
            var symbol = model.GetDeclaredSymbol(nsSyntax);
            Assert.Equal(string.Empty, symbol.Name);
        }
 
        [WorkItem(539740, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539740")]
        [Fact]
        public void FileScopedNamespaceWithoutName()
        {
            var text = "namespace;";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            comp.VerifyDiagnostics(
                // (1,10): error CS1001: Identifier expected
                // namespace;
                Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 10));
 
            var nsArray = tree.GetCompilationUnitRoot().DescendantNodes().Where(node => node.IsKind(SyntaxKind.FileScopedNamespaceDeclaration)).ToArray();
            Assert.Equal(1, nsArray.Length);
 
            var nsSyntax = nsArray[0] as FileScopedNamespaceDeclarationSyntax;
            var symbol = model.GetDeclaredSymbol(nsSyntax);
            Assert.Equal(string.Empty, symbol.Name);
        }
 
        [Fact]
        public void LazyBoundUsings1()
        {
            var text =
@"
// Peter Golde[7/19/2010]: I managed to construct the following interesting example today,
// which Dev10 does compile. Interestingly, the resolution of one ""using"" can depend
// on the resolution of another ""using"" later in the same namespace.
using K = A.Q;
using L = B.R;
 
class B
{
    public class R
    {
        public class Q
        {
            public class S : K { }
        }
    }
}
 
class A : L
{
    public K.S v = null;
}
";
            var comp = CreateCompilation(text);
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 0).Single();
            var abase = a.BaseType();
            Assert.Equal("B.R", abase.ToTestDisplayString());
 
            var b = global.GetTypeMembers("B", 0).Single();
            var r = b.GetTypeMembers("R", 0).Single();
            var q = r.GetTypeMembers("Q", 0).Single();
            var v = a.GetMembers("v").Single() as FieldSymbol;
            var s = v.Type;
            Assert.Equal("B.R.Q.S", s.ToTestDisplayString());
            var sbase = s.BaseType();
            Assert.Equal("B.R.Q", sbase.ToTestDisplayString());
        }
 
        [Fact]
        public void Diagnostics1()
        {
            var text =
@"
class A : A {}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
 
            var errs = comp.GetSemanticModel(tree).GetDeclarationDiagnostics();
            Assert.Equal(1, errs.Count());
        }
 
        [Fact]
        public void DiagnosticsInOneTree()
        {
            var partial1 =
@"
partial class A 
{ 
    void goo() { int x = y; }
}
 
class C : B {}
";
 
            var partial2 =
@"
partial class A 
{ 
    int q;      //an unused field in a partial type
    void bar() { int x = z; }
}
 
class B : NonExistent {}
";
 
            var partial1Tree = Parse(partial1);
            var partial2Tree = Parse(partial2);
            var comp = CreateCompilation(new SyntaxTree[] { partial1Tree, partial2Tree });
 
            var errs = comp.GetSemanticModel(partial1Tree).GetDiagnostics();
            Assert.Equal(1, errs.Count());
        }
 
        [Fact]
        public void Bindings1()
        {
            var text =
@"
class B : A {}
class A {}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
 
            var bdecl = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var bbase = bdecl.BaseList.Types[0].Type as TypeSyntax;
            var model = comp.GetSemanticModel(tree);
 
            var info = model.GetSymbolInfo(bbase);
            Assert.NotNull(info.Symbol);
            var a = comp.GlobalNamespace.GetTypeMembers("A", 0).Single().ISymbol;
            Assert.Equal(a, info.Symbol);
            Assert.Equal(a, model.GetTypeInfo(bbase).Type);
        }
 
        [Fact]
        public void BaseScope1()
        {
            // ensure the base clause is not bound in the scope of the class
            var text =
@"
public class C : B {}
public class A {
    public class B {}
}
public class B : A {}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
 
            var cdecl = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var cbase = cdecl.BaseList.Types[0].Type as TypeSyntax;
            var model = comp.GetSemanticModel(tree);
 
            var info = model.GetSymbolInfo(cbase);
            Assert.NotNull(info.Symbol);
            var b = comp.GlobalNamespace.GetTypeMembers("B", 0).Single().ISymbol;
            Assert.Equal(b, info.Symbol);
            Assert.Equal(b, model.GetTypeInfo(cbase).Type);
        }
 
        [Fact]
        public void BaseScope2()
        {
            // ensure type parameters are in scope in the base clause
            var text =
@"
public class C<T> : A<T> { }
public class A<T> : B { }
public class B {
    public class T { }
}
";
            var tree = Parse(text);
            var comp = (Compilation)CreateCompilation(tree);
 
            var cdecl = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var cbase = cdecl.BaseList.Types[0].Type as TypeSyntax;
            var model = comp.GetSemanticModel(tree);
 
            var info = model.GetSymbolInfo(cbase);
            Assert.NotNull(info.Symbol);
            var cbasetype = info.Symbol as INamedTypeSymbol;
 
            var c = comp.GlobalNamespace.GetTypeMembers("C", 1).Single();
            Assert.Equal(c.BaseType, cbasetype);
        }
 
        [Fact]
        public void Bindings2()
        {
            var text =
@"
class B<T> : A<T> {}
class A<T> {}
";
            var tree = Parse(text);
            var comp = (Compilation)CreateCompilation(tree);
 
            var bdecl = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var bbase = bdecl.BaseList.Types[0].Type as TypeSyntax; // A<T>
            var model = comp.GetSemanticModel(tree);
 
            var info = model.GetSymbolInfo(bbase);
            Assert.NotNull(info.Symbol);
            var at2 = info.Symbol as INamedTypeSymbol;
            Assert.Equal(at2, model.GetTypeInfo(bbase).Type);
 
            var a = comp.GlobalNamespace.GetTypeMembers("A", 1).Single();
            var at = a.TypeParameters.First();
            var b = comp.GlobalNamespace.GetTypeMembers("B", 1).Single();
            var bt = b.TypeParameters.First();
 
            Assert.Equal(a.OriginalDefinition, at2.OriginalDefinition);
            Assert.Equal(bt, at2.TypeArguments.First());
        }
 
        [Fact]
        public void Bindings3()
        {
            var text =
@"using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    static Program Field;
}";
            var tree1 = Parse(text);
            var compilation = CreateCompilation(tree1);
 
            var tree2 = Parse(text);
            var classProgram = tree2.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var staticProgramField = classProgram.Members[0] as FieldDeclarationSyntax;
            var program = staticProgramField.Declaration.Type;
            var model = compilation.GetSemanticModel(tree1);
 
            Assert.Throws<ArgumentException>(() =>
            {
                // tree2 not in the compilation
                var lookup = model.GetSymbolInfo(program);
            });
        }
 
        [Fact]
        public void Bindings4()
        {
            var text =
@"using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    Program p;
    static void Main(string[] args)
    {
    }
}";
 
            var tree1 = Parse(text);
            var compilation = (Compilation)CreateCompilation(tree1);
 
            var decl = tree1.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var field = decl.Members[0] as FieldDeclarationSyntax;
            var type = field.Declaration.Type;
            var model = compilation.GetSemanticModel(tree1);
 
            var info = model.GetSymbolInfo(type);
            Assert.Equal(compilation.GlobalNamespace.GetTypeMembers("Program", 0).Single(), info.Symbol);
        }
 
        [Fact]
        public void Bindings5()
        {
            var text =
@"using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    static void Main(string[] args)
    {
    }
}";
 
            var tree1 = Parse(text);
            var tree2 = Parse(text);
            var compilation = (Compilation)CreateCompilation(new SyntaxTree[] { tree1, tree2 });
 
            var decl = tree1.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var method = decl.Members[0] as MethodDeclarationSyntax;
            var type = method.ParameterList.Parameters[0].Type;
 
            var model = compilation.GetSemanticModel(tree1);
 
            var info = model.GetSymbolInfo(type);
            Assert.Equal(compilation.GetSpecialType(SpecialType.System_String), (info.Symbol as IArrayTypeSymbol).ElementType);
        }
 
        [Fact]
        public void Speculative1()
        {
            var text =
@"
class B {
    object x;
}
class A {}
";
            var tree = Parse(text);
            var comp = (Compilation)CreateCompilation(tree);
 
            var bdecl = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var xdecl = bdecl.Members[0] as FieldDeclarationSyntax;
 
            var model = comp.GetSemanticModel(tree);
 
            TypeSyntax speculate = SyntaxFactory.IdentifierName(SyntaxFactory.Identifier("A"));
            var symbolInfo = model.GetSpeculativeSymbolInfo(xdecl.SpanStart, speculate, SpeculativeBindingOption.BindAsTypeOrNamespace);
            var lookup = symbolInfo.Symbol as ITypeSymbol;
 
            Assert.NotNull(lookup);
            var a = comp.GlobalNamespace.GetTypeMembers("A", 0).Single();
            Assert.Equal(a, lookup);
        }
 
        [Fact]
        public void GetType1()
        {
            var text =
@"
class A {
    class B {}
}
";
            var tree = Parse(text);
            var comp = (Compilation)CreateCompilation(tree);
 
            var adecl = tree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var bdecl = adecl.Members[0] as TypeDeclarationSyntax;
 
            var model = comp.GetSemanticModel(tree);
            var a1 = model.GetDeclaredSymbol(adecl);
            var b1 = model.GetDeclaredSymbol(bdecl);
 
            var global = comp.GlobalNamespace;
            var a2 = global.GetTypeMembers("A", 0).Single();
            var b2 = a2.GetTypeMembers("B", 0).Single();
 
            Assert.Equal(a2, a1);
            Assert.Equal(b2, b1);
        }
 
        [Fact]
        public void DottedName()
        {
            var text =
@"
class Main {
  A.B x; // this refers to the B within A.
}
class A {
    public class B {}
}
class B {}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = (CSharpSemanticModel)comp.GetSemanticModel(tree);
 
            var root = tree.GetCompilationUnitRoot();
            var mainDecl = root.Members[0] as TypeDeclarationSyntax;
            var mainType = model.GetDeclaredSymbol(mainDecl);
 
            var aDecl = root.Members[1] as TypeDeclarationSyntax;
            var aType = model.GetDeclaredSymbol(aDecl);
 
            var abDecl = aDecl.Members[0] as TypeDeclarationSyntax;
            var abType = model.GetDeclaredSymbol(abDecl);
 
            var bDecl = root.Members[2] as TypeDeclarationSyntax;
            var bType = model.GetDeclaredSymbol(bDecl);
 
            var xDecl = mainDecl.Members[0] as FieldDeclarationSyntax;
            var xSym = mainType.GetMembers("x").Single() as IFieldSymbol;
            Assert.Equal<ISymbol>(abType, xSym.Type);
            var info = model.GetSymbolInfo((xDecl.Declaration.Type as QualifiedNameSyntax).Right);
            Assert.Equal(abType, info.Symbol);
        }
 
        [Fact]
        public void AliasQualifiedName()
        {
            var text =
@"
class B {}
namespace N {
  class C : global::B {}
  class B {}
}
";
            var tree = Parse(text);
            var comp = (Compilation)CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
 
            var root = tree.GetCompilationUnitRoot();
            var nDecl = root.Members[0] as NamespaceDeclarationSyntax;
            var n2Decl = root.Members[1] as NamespaceDeclarationSyntax;
            var cDecl = n2Decl.Members[0] as TypeDeclarationSyntax;
            var cBase = (cDecl.BaseList.Types[0].Type as AliasQualifiedNameSyntax).Name;
 
            var cBaseType = model.GetSymbolInfo(cBase).Symbol;
            var bOuter = comp.GlobalNamespace.GetTypeMembers("B", 0).Single();
            var bInner = (comp.GlobalNamespace.GetMembers("N").Single() as INamespaceSymbol).GetTypeMembers("B", 0).Single();
            Assert.Equal(bOuter, cBaseType);
        }
 
        [Fact, WorkItem(528655, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528655")]
        public void ErrorSymbolForInvalidCode()
        {
            var text = @"
public class A 
{
	int goo	{	void goo() {}	} // Error
	static int Main() {	return 1;    }
}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var mems = comp.SourceModule.GlobalNamespace.GetMembers();
 
            var typeA = mems.Where(s => s.Name == "A").Select(s => s);
            Assert.Equal(1, typeA.Count());
            var invalid = mems.Where(s => s.Name == WellKnownMemberNames.TopLevelStatementsEntryPointTypeName).Select(s => s);
            Assert.Equal(1, invalid.Count());
        }
 
        [Fact, WorkItem(543225, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543225"), WorkItem(529057, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529057")]
        public void MergePartialMethodAndParameterSymbols()
        {
            var text = @"
using System;
 
partial class PC
{
    partial void PM(int pp);
}
 
partial class PC
{
    partial void PM(int pp) {}
}
";
            var tree = Parse(text);
            var comp = (Compilation)CreateCompilation(tree);
            var pTypeSym = comp.SourceModule.GlobalNamespace.GetTypeMembers("PC").Single();
            var pMethodSym = pTypeSym.GetMembers("PM").Single();
 
            var model = (CSharpSemanticModel)comp.GetSemanticModel(tree);
            var pType01 = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().First();
            var pType02 = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().Last();
            Assert.NotEqual(pType01, pType02);
            var ptSym01 = model.GetDeclaredSymbol(pType01);
            var ptSym02 = model.GetDeclaredSymbol(pType02);
            // same partial type symbol
            Assert.Same(ptSym01, ptSym02);
            Assert.Equal(2, ptSym01.Locations.Length);
 
            var pMethod01 = tree.GetCompilationUnitRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
            var pMethod02 = tree.GetCompilationUnitRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Last();
            Assert.NotEqual(pMethod01, pMethod02);
 
            var pmSym01 = model.GetDeclaredSymbol(pMethod01);
            var pmSym02 = model.GetDeclaredSymbol(pMethod02);
            // different partial method symbols:(
            Assert.NotSame(pmSym01, pmSym02);
            // the declaration one is what one can get from GetMembers()
            Assert.Same(pMethodSym, pmSym01);
 
            // with decl|impl point to each other
            Assert.Null(pmSym01.PartialDefinitionPart);
            Assert.Same(pmSym02, pmSym01.PartialImplementationPart);
 
            Assert.Same(pmSym01, pmSym02.PartialDefinitionPart);
            Assert.Null(pmSym02.PartialImplementationPart);
 
            var pParam01 = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().First();
            var pParam02 = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().Last();
            Assert.NotEqual(pParam01, pParam02);
 
            var ppSym01 = model.GetDeclaredSymbol(pParam01);
            var ppSym02 = model.GetDeclaredSymbol(pParam02);
            Assert.NotSame(ppSym01, ppSym02);
            Assert.Equal(1, ppSym01.Locations.Length);
            Assert.Equal(1, ppSym02.Locations.Length);
        }
 
        [Fact, WorkItem(544221, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544221")]
        public void GetTypeInfoForOptionalParameterDefaultValueInDelegate()
        {
            var text = @"
using System;
 
class Test
{
    public delegate void DGoo(byte i = 1);
    protected internal void MGoo(sbyte j = 2) { }
}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            var root = tree.GetCompilationUnitRoot();
            var exprs = root.DescendantNodes().OfType<LiteralExpressionSyntax>().ToArray();
            Assert.Equal(2, exprs.Length);
 
            var type1 = model.GetTypeInfo(exprs[0]);
            var type2 = model.GetTypeInfo(exprs[1]);
 
            Assert.NotNull(type1.Type);
            Assert.Equal("System.Int32", type1.Type.ToTestDisplayString());
            Assert.NotNull(type2.Type);
            Assert.Equal("System.Int32", type2.Type.ToTestDisplayString());
        }
 
        [Fact, WorkItem(544231, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544231")]
        public void GetDeclSymbolForParameterOfPartialMethod()
        {
            var text1 = @"
using System;
 
partial class Partial001
{
    static partial void Goo(ulong x);
}
";
 
            var text2 = @"
using System;
 
partial class Partial001
{
    static partial void Goo(ulong x)  {    }
    static int Main()  {    return 1;    }
}
";
            var tree1 = Parse(text1);
            var tree2 = Parse(text2);
            var comp = CreateCompilation(new[] { tree1, tree2 });
 
            var model1 = comp.GetSemanticModel(tree1);
            var model2 = comp.GetSemanticModel(tree2);
            var root1 = tree1.GetCompilationUnitRoot();
            var root2 = tree1.GetCompilationUnitRoot();
            var para1 = tree1.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().First();
            var para2 = tree2.GetCompilationUnitRoot().DescendantNodes().OfType<ParameterSyntax>().First();
            var sym1 = model1.GetDeclaredSymbol(para1);
            var sym2 = model2.GetDeclaredSymbol(para2);
 
            Assert.NotNull(sym1);
            Assert.NotNull(sym2);
            Assert.Equal("System.UInt64 x", sym1.ToTestDisplayString());
            Assert.Equal("System.UInt64 x", sym2.ToTestDisplayString());
            Assert.NotEqual(sym1.Locations[0], sym2.Locations[0]);
        }
 
        [Fact, WorkItem(544473, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544473")]
        public void GetDeclSymbolForTypeParameterOfPartialMethod()
        {
            var text1 = @"
using System;
 
partial class Partial001
{
    static partial void Goo<T>(T x);
}
";
 
            var text2 = @"
using System;
 
partial class Partial001
{
    static partial void Goo<T>(T x)  {    }
    static int Main()  {    return 1;    }
}
";
            var tree1 = Parse(text1);
            var tree2 = Parse(text2);
            var comp = CreateCompilation(new List<SyntaxTree> { tree1, tree2 });
 
            var model1 = comp.GetSemanticModel(tree1);
            var model2 = comp.GetSemanticModel(tree2);
            var root1 = tree1.GetCompilationUnitRoot();
            var root2 = tree1.GetCompilationUnitRoot();
            var para1 = tree1.GetCompilationUnitRoot().DescendantNodes().OfType<TypeParameterSyntax>().First();
            var para2 = tree2.GetCompilationUnitRoot().DescendantNodes().OfType<TypeParameterSyntax>().First();
            var sym1 = model1.GetDeclaredSymbol(para1);
            var sym2 = model2.GetDeclaredSymbol(para2);
 
            Assert.NotNull(sym1);
            Assert.NotNull(sym2);
            Assert.Equal("T", sym1.ToTestDisplayString());
            Assert.Equal("T", sym2.ToTestDisplayString());
            Assert.NotEqual(sym1.Locations[0], sym2.Locations[0]);
        }
 
        [Fact]
        public void GetDeclaredSymbolForAnonymousTypeProperty01()
        {
            var text = @"
using System;
 
struct AnonTypeTest
{
    static long Prop
    {
        get
        {
            short @short = -1;
            var anonType = new { id = 123, @do = ""QC"", @short, Prop };
            return anonType.id + anonType.@short;
        }
    }
}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            var anonProps = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AnonymousObjectMemberDeclaratorSyntax>();
            Assert.Equal(4, anonProps.Count());
            var symList = from ap in anonProps
                          let apsym = model.GetDeclaredSymbol(ap)
                          orderby apsym.Name
                          select apsym.Name;
 
            var results = string.Join(", ", symList);
            Assert.Equal("do, id, Prop, short", results);
        }
 
        [Fact]
        public void GetDeclaredSymbolForAnonymousTypeProperty02()
        {
            var text = @"
using System;
 
class AnonTypeTest
{
    long field = 111;
    void M(byte p1, ref sbyte p2, out string p3, params string[] ary)
    {
        ulong local = 12345;
        var anonType = new { local, this.field, p1, p2, ary };
        p3 = anonType.ary.Length > 0 ? anonType.ary[0] : """";
    }
}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            var anonProps = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AnonymousObjectMemberDeclaratorSyntax>();
            Assert.Equal(5, anonProps.Count());
            var symList = from ap in anonProps
                          let apsym = model.GetDeclaredSymbol(ap)
                          orderby apsym.Name
                          select apsym.Name;
 
            var results = string.Join(", ", symList);
            Assert.Equal("ary, field, local, p1, p2", results);
        }
 
        [Fact]
        public void GetDeclaredSymbolForAnonymousTypeProperty03()
        {
            var text = @"
using System;
 
enum E { a, b, c }
class Base
{
    protected E baseField = E.b;
    protected virtual Base BaseProp { get { return this; } }
    public Func<string, char> deleField;
}
 
class AnonTypeTest : Base
{
    protected override Base BaseProp { get { return null; } }
    char this[string @string]
    {
        get
        {
            var anonType = new { id = deleField, base.BaseProp, base.baseField, ret = @string };
            return anonType.id(anonType.ret);
        }
    }
}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            var anonProps = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AnonymousObjectMemberDeclaratorSyntax>();
            Assert.Equal(4, anonProps.Count());
            var symList = from ap in anonProps
                          let apsym = model.GetDeclaredSymbol(ap)
                          orderby apsym.Name
                          select apsym.Name;
 
            var results = string.Join(", ", symList);
            Assert.Equal("baseField, BaseProp, id, ret", results);
        }
 
        [Fact]
        public void GetDeclaredSymbolForAnonymousTypeProperty04()
        {
            var text = @"
using System;
 
enum E { a, b, c }
struct S
{
    public static E sField;
    public interface IGoo {  }
    public IGoo GetGoo { get; set; }
    public IGoo GetGoo2() { return null; }
}
 
class AnonTypeTest
{
    event Action<ushort> Eve
    {
        add
        {
            var anonType = new { a1 = new { S.sField, igoo = new { new S().GetGoo } } };
        }
        remove 
        {
            var anonType = new { a1 = new { a2 = new { a2 = S.sField, a3 = new { a3 = new S().GetGoo2() } } } };
        }
    }
}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            var anonProps = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AnonymousObjectMemberDeclaratorSyntax>();
            Assert.Equal(9, anonProps.Count());
            var symList = from ap in anonProps
                          let apsym = model.GetDeclaredSymbol(ap)
                          orderby apsym.Name
                          select apsym.Name;
 
            var results = string.Join(", ", symList);
            Assert.Equal("a1, a1, a2, a2, a3, a3, GetGoo, igoo, sField", results);
        }
 
        [Fact(), WorkItem(542861, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542861"), WorkItem(529673, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529673")]
        public void GetSymbolInfoForAccessorParameters()
        {
            var text = @"
using System;
 
public class Test
{
    object[] _Items = new object[3];
    public object this[int index]
    {
        get
        {
            return _Items[index];
        }
        set
        {
            _Items[index] = value;
        }
    } 
}
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            var model = comp.GetSemanticModel(tree);
            var descendants = tree.GetCompilationUnitRoot().DescendantNodes();
 
            var paras = descendants.OfType<ParameterSyntax>();
            Assert.Equal(1, paras.Count());
            var parasym = model.GetDeclaredSymbol(paras.First());
            var ploc = parasym.Locations[0];
 
            var args = descendants.OfType<ArgumentSyntax>().Where(s => s.ToString() == "index").Select(s => s);
            Assert.Equal(2, args.Count());
            var argsym1 = model.GetSymbolInfo(args.First().Expression).Symbol;
            var argsym2 = model.GetSymbolInfo(args.Last().Expression).Symbol;
            Assert.NotNull(argsym1);
            Assert.NotNull(argsym2);
 
            Assert.Equal(ploc, argsym1.Locations[0]);
            Assert.Equal(ploc, argsym2.Locations[0]);
 
            Assert.Equal(parasym.Kind, argsym1.Kind);
            Assert.Equal(parasym.Kind, argsym2.Kind);
 
            // SourceSimpleParameterSymbol vs. SourceClonedComplexParameterSymbol
            Assert.NotEqual(parasym, argsym1);
            Assert.NotEqual(parasym, argsym2);
        }
 
        [WorkItem(545648, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545648")]
        [Fact]
        public void AliasDeclaredSymbolWithConflict()
        {
            var source = @"
using X = System;
 
class X { }
";
 
            var comp = (Compilation)CreateCompilation(source);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var aliasSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Single();
 
            var symbol = model.GetDeclaredSymbol(aliasSyntax);
            Assert.Equal(symbol.Target, comp.GlobalNamespace.GetMember<INamespaceSymbol>("System"));
 
            comp.VerifyDiagnostics(
                // (2,1): info CS8019: Unnecessary using directive.
                // using X = System;
                Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using X = System;"));
        }
 
        [WorkItem(529751, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529751")]
        [Fact]
        public void ExternAlias()
        {
            var source = @"
extern alias X;
 
class Test
{
    static void Main()
    {
        X::C c = null;
    }
}
";
            var comp1 = CreateCompilation("public class C { }");
            var ref1 = comp1.EmitToImageReference(aliases: ImmutableArray.Create("X"));
 
            var comp2 = CreateCompilation(source, new[] { ref1 });
            var tree = comp2.SyntaxTrees.Single();
            var model = comp2.GetSemanticModel(tree);
 
            var aliasSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ExternAliasDirectiveSyntax>().Single();
 
            // Compilation.GetExternAliasTarget defines this behavior: the target is a merged namespace
            // with the same name as the alias, contained in the global namespace of the compilation.
            var aliasSymbol = model.GetDeclaredSymbol(aliasSyntax);
            var aliasTarget = (INamespaceSymbol)aliasSymbol.Target;
            Assert.Equal(NamespaceKind.Module, aliasTarget.NamespaceKind);
            Assert.Equal("", aliasTarget.Name);
            Assert.True(aliasTarget.IsGlobalNamespace);
            Assert.Null(aliasTarget.ContainingNamespace);
 
            Assert.Equal(0, comp2.GlobalNamespace.GetMembers("X").Length); //Doesn't contain the alias target namespace as a child.
 
            var aliasQualifiedSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AliasQualifiedNameSyntax>().Single();
            Assert.Equal(aliasSymbol, model.GetAliasInfo(aliasQualifiedSyntax.Alias));
 
            comp2.VerifyDiagnostics(
                // (8,14): warning CS0219: The variable 'c' is assigned but its value is never used
                //         X::C c = null;
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "c").WithArguments("c"));
        }
 
        [Fact, WorkItem(546687, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546687"), WorkItem(529751, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529751")]
        public void ExternAliasWithoutTarget()
        {
            var source = @"
extern alias X;
 
class Test
{
    static void Main()
    {
        X::C c = null;
    }
}
";
 
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var aliasSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ExternAliasDirectiveSyntax>().Single();
 
            var aliasSymbol = model.GetDeclaredSymbol(aliasSyntax);
            Assert.IsType<MissingNamespaceSymbol>(aliasSymbol.Target.GetSymbol());
 
            var aliasQualifiedSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<AliasQualifiedNameSyntax>().Single();
            Assert.Equal(aliasSymbol, model.GetAliasInfo(aliasQualifiedSyntax.Alias));
 
            comp.VerifyDiagnostics(
                // (2,14): error CS0430: The extern alias 'X' was not specified in a /reference option
                // extern alias X;
                Diagnostic(ErrorCode.ERR_BadExternAlias, "X").WithArguments("X"),
                // (8,12): error CS0234: The type or namespace name 'C' does not exist in the namespace 'X' (are you missing an assembly reference?)
                //         X::C c = null;
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "C").WithArguments("C", "X"));
        }
 
        [WorkItem(545648, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545648")]
        [Fact]
        public void UsingDirectiveAliasSemanticInfo()
        {
            var source = "using X = System;";
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (1,1): info CS8019: Unnecessary using directive.
                // using X = System;
                Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using X = System;"));
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var aliasSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<NameEqualsSyntax>().Single().Name;
            Assert.Equal(SymbolInfo.None, model.GetSymbolInfo(aliasSyntax));
 
            var usingSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Single();
            Assert.Equal(SymbolKind.Alias, model.GetDeclaredSymbol(usingSyntax).Kind);
        }
 
        [WorkItem(545882, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545882")]
        [Fact]
        public void SpeculativelyBindConstructorInitializerInPlaceOfActual()
        {
            var source = @"class C
{
    C(int x) { }
    C() : this((int) 1) { }
}";
 
            var comp = (Compilation)CreateCompilation(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var oldSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ConstructorInitializerSyntax>().Single();
 
            var newSyntax = SyntaxFactory.ConstructorInitializer(SyntaxKind.ThisConstructorInitializer);
 
            var info = model.GetSpeculativeSymbolInfo(oldSyntax.SpanStart, newSyntax);
            var symbol = info.Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C"), symbol.ContainingType);
            Assert.Equal(SymbolKind.Method, symbol.Kind);
            var method = (IMethodSymbol)symbol;
            Assert.Equal(MethodKind.Constructor, method.MethodKind);
            Assert.Empty(method.Parameters);
        }
 
        [WorkItem(545882, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545882")]
        [Fact]
        public void SpeculativelyBindConstructorInitializerInNewLocation()
        {
            var source = @"class C
{
    C() { }
}";
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var oldSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            var newSyntax = SyntaxFactory.ConstructorInitializer(SyntaxKind.ThisConstructorInitializer);
 
            var info = model.GetSpeculativeSymbolInfo(oldSyntax.ParameterList.Span.End, newSyntax);
            Assert.Equal(SymbolInfo.None, info);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelInFieldInitializer()
        {
            var compilation = CreateCompilation(@"
class C 
{
  object y = 1;
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var fieldDecl = (FieldDeclarationSyntax)typeDecl.Members[0];
            var varDecl = fieldDecl.Declaration.Variables.First();
 
            var model = compilation.GetSemanticModel(tree);
            Assert.False(model.IsSpeculativeSemanticModel);
            Assert.Null(model.ParentModel);
            Assert.Equal(0, model.OriginalPositionForSpeculation);
 
            // Speculate on the equals value syntax (initializer)
            // Conversion info available, ConvertedType: Object.
            var equalsValue = SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression(@"(string)""Hello"""));
            var expr = equalsValue.Value;
            int position = varDecl.Initializer.SpanStart;
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(position, equalsValue, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
            Assert.True(speculativeModel.IsSpeculativeSemanticModel);
            Assert.Equal(model, speculativeModel.ParentModel);
            Assert.Equal(position, speculativeModel.OriginalPositionForSpeculation);
 
            var typeInfo = speculativeModel.GetTypeInfo(expr);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("String", typeInfo.Type.Name);
            Assert.Equal("Object", typeInfo.ConvertedType.Name);
 
            var constantInfo = speculativeModel.GetConstantValue(expr);
            Assert.True(constantInfo.HasValue, "must be a constant");
            Assert.Equal("Hello", constantInfo.Value);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelInEnumMember()
        {
            var compilation = CreateCompilation(@"
enum C 
{
  y = 1
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (EnumDeclarationSyntax)root.Members[0];
            var enumMemberDecl = (EnumMemberDeclarationSyntax)typeDecl.Members[0];
            var equalsValue = enumMemberDecl.EqualsValue;
            var initializer = equalsValue.Value;
 
            var model = compilation.GetSemanticModel(tree);
 
            // Speculate on the equals value syntax (initializer)
            // Conversion info available, ConvertedType: Int32.
            var newEqualsValue = SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression("(short)0"));
            var expr = newEqualsValue.Value;
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(equalsValue.SpanStart, newEqualsValue, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
            Assert.False(speculativeModel.IgnoresAccessibility);
 
            var typeInfo = speculativeModel.GetTypeInfo(expr);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("Int16", typeInfo.Type.Name);
            Assert.Equal("Int32", typeInfo.ConvertedType.Name);
 
            var constantInfo = speculativeModel.GetConstantValue(expr);
            Assert.True(constantInfo.HasValue, "must be a constant");
            Assert.Equal((short)0, constantInfo.Value);
 
            model = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
            model.TryGetSpeculativeSemanticModel(equalsValue.SpanStart, newEqualsValue, out speculativeModel);
            Assert.True(speculativeModel.IgnoresAccessibility);
        }
 
        [Fact]
        [WorkItem(648305, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/648305")]
        public void TestGetSpeculativeSemanticModelInDefaultValueArgument()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x = 1)
  {
    string y = ""Hello"";     
  }
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var equalsValue = methodDecl.ParameterList.Parameters[0].Default;
            var paramDefaultArg = equalsValue.Value;
 
            var model = compilation.GetSemanticModel(tree);
 
            var ti = model.GetTypeInfo(paramDefaultArg);
 
            // Speculate on the equals value syntax (initializer)
            // Conversion info available, ConvertedType: Int32.
            var newEqualsValue = SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression("(short)0"));
            var expr = newEqualsValue.Value;
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(equalsValue.SpanStart, newEqualsValue, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var typeInfo = speculativeModel.GetTypeInfo(expr);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("Int16", typeInfo.Type.Name);
            Assert.Equal("Int32", typeInfo.ConvertedType.Name);
 
            var constantInfo = speculativeModel.GetConstantValue(expr);
            Assert.True(constantInfo.HasValue, "must be a constant");
            Assert.Equal((short)0, constantInfo.Value);
        }
 
        [Fact]
        [WorkItem(746002, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/746002")]
        public void TestGetSpeculativeSemanticModelInDefaultValueArgument2()
        {
            var compilation = CreateCompilation(@"
using System;
 
enum E
{
   A = 1,
   B = 2  
}
 
interface I
{
    void M1(E e = E.A);
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var interfaceDecl = (TypeDeclarationSyntax)root.Members[1];
            var methodDecl = (MethodDeclarationSyntax)interfaceDecl.Members[0];
            var param = methodDecl.ParameterList.Parameters[0];
            var equalsValue = param.Default;
            var paramDefaultArg = equalsValue.Value;
 
            var model = compilation.GetSemanticModel(tree);
 
            // Speculate on the equals value syntax (initializer) with a non-null parent
            var newEqualsValue = SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression("E.B | E.A"));
            newEqualsValue = param.ReplaceNode(equalsValue, newEqualsValue).Default;
            var binaryExpr = newEqualsValue.Value;
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(equalsValue.SpanStart, newEqualsValue, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var typeInfo = speculativeModel.GetTypeInfo(binaryExpr);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("E", typeInfo.Type.Name);
            Assert.Equal("E", typeInfo.ConvertedType.Name);
        }
 
        [Fact]
        [WorkItem(657701, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/657701")]
        public void TestGetSpeculativeSemanticModelInConstructorDefaultValueArgument()
        {
            var compilation = CreateCompilation(@"
class C 
{
  C(int x = 1)
  {
    string y = ""Hello"";     
  }
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var constructorDecl = (ConstructorDeclarationSyntax)typeDecl.Members[0];
            var equalsValue = constructorDecl.ParameterList.Parameters[0].Default;
            var paramDefaultArg = equalsValue.Value;
 
            var model = compilation.GetSemanticModel(tree);
 
            var ti = model.GetTypeInfo(paramDefaultArg);
 
            // Speculate on the equals value syntax (initializer)
            // Conversion info available, ConvertedType: Int32.
            var newEqualsValue = SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression("(short)0"));
            var expr = newEqualsValue.Value;
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(equalsValue.SpanStart, newEqualsValue, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var typeInfo = speculativeModel.GetTypeInfo(expr);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("Int16", typeInfo.Type.Name);
            Assert.Equal("Int32", typeInfo.ConvertedType.Name);
 
            var constantInfo = speculativeModel.GetConstantValue(expr);
            Assert.True(constantInfo.HasValue, "must be a constant");
            Assert.Equal((short)0, constantInfo.Value);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelInExpressionBody_Property()
        {
            var compilation = CreateCompilation(@"
class C 
{
  public object X => 0;
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var propertyDecl = (PropertyDeclarationSyntax)typeDecl.Members[0];
            var expressionBody = propertyDecl.ExpressionBody;
 
            TestExpressionBodySpeculation(compilation, tree, expressionBody);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelInExpressionBody_Method()
        {
            var compilation = CreateCompilation(@"
class C 
{
  public object X() => 0;
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var expressionBody = methodDecl.ExpressionBody;
 
            TestExpressionBodySpeculation(compilation, tree, expressionBody);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelInExpressionBody_Indexer()
        {
            var compilation = CreateCompilation(@"
class C 
{
  public object this[int x] => 0;
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var indexerDecl = (IndexerDeclarationSyntax)typeDecl.Members[0];
            var expressionBody = indexerDecl.ExpressionBody;
 
            TestExpressionBodySpeculation(compilation, tree, expressionBody);
        }
 
        private static void TestExpressionBodySpeculation(Compilation compilation, SyntaxTree tree, ArrowExpressionClauseSyntax expressionBody)
        {
            var model = compilation.GetSemanticModel(tree);
            Assert.False(model.IsSpeculativeSemanticModel);
            Assert.Null(model.ParentModel);
            Assert.Equal(0, model.OriginalPositionForSpeculation);
 
            // Speculate on the expression body syntax.
            // Conversion info available, ConvertedType: Object.
            var newExpressionBody = SyntaxFactory.ArrowExpressionClause(SyntaxFactory.ParseExpression(@"(string)""Hello"""));
            var expr = newExpressionBody.Expression;
            int position = expressionBody.SpanStart;
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(position, newExpressionBody, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
            Assert.True(speculativeModel.IsSpeculativeSemanticModel);
            Assert.Equal(model, speculativeModel.ParentModel);
            Assert.Equal(position, speculativeModel.OriginalPositionForSpeculation);
 
            var typeInfo = speculativeModel.GetTypeInfo(expr);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("String", typeInfo.Type.Name);
            Assert.Equal("Object", typeInfo.ConvertedType.Name);
 
            var constantInfo = speculativeModel.GetConstantValue(expr);
            Assert.True(constantInfo.HasValue, "must be a constant");
            Assert.Equal("Hello", constantInfo.Value);
        }
 
        [WorkItem(529893, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529893")]
        [Fact]
        public void AliasCalledVar()
        {
            var source = @"
using @var = Q;
 
class Q
{
    var q;
}
";
 
            var comp = (Compilation)CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (6,9): warning CS0169: The field 'Q.q' is never used
                //     var q;
                Diagnostic(ErrorCode.WRN_UnreferencedField, "q").WithArguments("Q.q"));
 
            var classQ = comp.GlobalNamespace.GetMember<INamedTypeSymbol>("Q");
            var fieldQ = classQ.GetMember<IFieldSymbol>("q");
 
            Assert.Equal(classQ, fieldQ.Type);
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var aliasDecl = tree.GetRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Single();
 
            var aliasSymbol = model.GetDeclaredSymbol(aliasDecl);
            Assert.Equal(SymbolKind.Alias, aliasSymbol.Kind);
            Assert.Equal(classQ, aliasSymbol.Target);
            Assert.Equal("var", aliasSymbol.Name);
 
            var aliasDeclInfo = model.GetSymbolInfo(aliasDecl.Alias.Name);
            Assert.Null(aliasDeclInfo.Symbol);
            Assert.Equal(CandidateReason.None, aliasDeclInfo.CandidateReason);
 
            var fieldDecl = tree.GetRoot().DescendantNodes().OfType<FieldDeclarationSyntax>().Single();
 
            var fieldSymbol = model.GetDeclaredSymbol(fieldDecl.Declaration.Variables.Single());
            Assert.Equal(fieldQ, fieldSymbol);
 
            var typeSyntax = (IdentifierNameSyntax)fieldDecl.Declaration.Type;
 
            var fieldTypeInfo = model.GetSymbolInfo(typeSyntax);
            Assert.Equal(classQ, fieldTypeInfo.Symbol);
 
            var fieldTypeAliasInfo = model.GetAliasInfo(typeSyntax);
            Assert.Equal(aliasSymbol, fieldTypeAliasInfo);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForStatement()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    int y = 1000;     
  }
}
");
 
            var statement = (BlockSyntax)SyntaxFactory.ParseStatement(@"
{ 
   int z = 0; 
   M(z);  
   M(y);
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].SpanStart, statement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var localDecl = (LocalDeclarationStatementSyntax)statement.Statements[0];
            var declarator = localDecl.Declaration.Variables.First();
            var local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("z", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("Int32", ((ILocalSymbol)local).Type.Name);
 
            var typeInfo = speculativeModel.GetTypeInfo(localDecl.Declaration.Type);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("Int32", typeInfo.Type.Name);
 
            var call = (InvocationExpressionSyntax)((ExpressionStatementSyntax)statement.Statements[1]).Expression;
            var arg = call.ArgumentList.Arguments[0].Expression;
            var info = speculativeModel.GetSymbolInfo(arg);
            Assert.NotNull(info.Symbol);
            Assert.Equal("z", info.Symbol.Name);
            Assert.Equal(SymbolKind.Local, info.Symbol.Kind);
 
            var call2 = (InvocationExpressionSyntax)((ExpressionStatementSyntax)((BlockSyntax)statement).Statements[2]).Expression;
            var arg2 = call2.ArgumentList.Arguments[0].Expression;
            var info2 = speculativeModel.GetSymbolInfo(arg2);
            Assert.NotNull(info2.Symbol);
            Assert.Equal("y", info2.Symbol.Name);
            Assert.Equal(SymbolKind.Local, info2.Symbol.Kind);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForStatement_DeclaredLocal()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    int y = 1000;
  }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            // different name local
            var statement = SyntaxFactory.ParseStatement(@"int z = 0;");
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].SpanStart, statement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var declarator = ((LocalDeclarationStatementSyntax)statement).Declaration.Variables.First();
            var local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("z", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("Int32", ((ILocalSymbol)local).Type.Name);
 
            // same name local
            statement = SyntaxFactory.ParseStatement(@"string y = null;");
            success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].SpanStart, statement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            declarator = ((LocalDeclarationStatementSyntax)statement).Declaration.Variables.First();
            local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("y", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("String", ((ILocalSymbol)local).Type.Name);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForStatement_GetDeclaredLabelSymbol()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    int y = 1000;     
  }
}
");
 
            var labeledStatement = SyntaxFactory.ParseStatement(@"label: y++;");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            SemanticModel statModel;
            bool success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].SpanStart, labeledStatement, out statModel);
            Assert.True(success);
            Assert.NotNull(statModel);
 
            var label = statModel.GetDeclaredSymbol(labeledStatement);
            Assert.NotNull(label);
            Assert.Equal("label", label.Name);
            Assert.Equal(SymbolKind.Label, label.Kind);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForStatement_GetDeclaredSwitchLabelSymbol()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    int y = 0;
  }
}
");
 
            var switchStatement = (SwitchStatementSyntax)SyntaxFactory.ParseStatement(@"
switch (y)
{
  case 0:
    y++;
    break;
}");
            var switchLabel = switchStatement.Sections[0].Labels[0];
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
            SemanticModel statModel;
            bool success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].Span.End, switchStatement, out statModel);
            Assert.True(success);
            Assert.NotNull(statModel);
 
            var symbol = ((CSharp.Symbols.PublicModel.LabelSymbol)statModel.GetDeclaredSymbol(switchLabel))?.UnderlyingSymbol;
            Assert.NotNull(symbol);
            Assert.IsType<SourceLabelSymbol>(symbol);
 
            var labelSymbol = (SourceLabelSymbol)symbol;
            Assert.Equal(ConstantValue.Default(SpecialType.System_Int32), labelSymbol.SwitchCaseLabelConstant);
            Assert.Equal(switchLabel, labelSymbol.IdentifierNodeOrToken.AsNode());
            Assert.Equal("case 0:", labelSymbol.Name);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForStatement_GetDeclaredLambdaParameterSymbol()
        {
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(@"
using System.Linq;
 
class C 
{
  void M(int x)
  {
    int y = 0;
  }
}
");
 
            var speculatedStatement = (LocalDeclarationStatementSyntax)SyntaxFactory.ParseStatement(@"Func<int, int> var = (z) => x + z;");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].Span.End, speculatedStatement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var lambdaExpression = speculatedStatement.DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().FirstOrDefault();
            var lambdaParam = lambdaExpression.ParameterList.Parameters[0];
            var parameterSymbol = speculativeModel.GetDeclaredSymbol(lambdaParam);
            Assert.NotNull(parameterSymbol);
            Assert.Equal("z", parameterSymbol.Name);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForStatement_ForEach()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    var a = new [] {1, 2, 3};     
  }
}
");
 
            var statement = (ForEachStatementSyntax)SyntaxFactory.ParseStatement(@"
foreach(short ele in a)
{
} 
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].SpanStart, statement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            ForEachStatementInfo info = speculativeModel.GetForEachStatementInfo(statement);
            Assert.NotEqual(default, info);
            Assert.Equal("System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()", info.GetEnumeratorMethod.ToTestDisplayString());
            Assert.Equal("System.Object System.Collections.IEnumerator.Current.get", info.CurrentProperty.GetMethod.ToTestDisplayString());
            Assert.Equal("System.Boolean System.Collections.IEnumerator.MoveNext()", info.MoveNextMethod.ToTestDisplayString());
            Assert.Equal("void System.IDisposable.Dispose()", info.DisposeMethod.ToTestDisplayString());
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelInAutoPropInitializer1()
        {
            var source = @"class C
{
    int y = 0;
    int X { get; } = 1;
}";
 
            var comp = CreateCompilation(source, parseOptions: TestOptions.Regular);
            var tree = comp.SyntaxTrees.Single();
 
            var model = comp.GetSemanticModel(tree);
            Assert.False(model.IsSpeculativeSemanticModel);
            Assert.Null(model.ParentModel);
            Assert.Equal(0, model.OriginalPositionForSpeculation);
 
            // Speculate on the initializer
            var root = tree.GetCompilationUnitRoot();
            var oldSyntax = root.DescendantNodes()
                .OfType<EqualsValueClauseSyntax>().ElementAt(1);
            var position = oldSyntax.SpanStart;
            var newSyntax = SyntaxFactory.EqualsValueClause(
                SyntaxFactory.ParseExpression("this.y"));
            var expr = newSyntax.Value;
 
            SemanticModel speculativeModel;
            bool success = model.TryGetSpeculativeSemanticModel(oldSyntax.SpanStart,
                newSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
            Assert.True(speculativeModel.IsSpeculativeSemanticModel);
            Assert.Equal(model, speculativeModel.ParentModel);
            Assert.Equal(position, speculativeModel.OriginalPositionForSpeculation);
 
            var typeInfo = speculativeModel.GetTypeInfo(expr);
            Assert.NotEqual(default, typeInfo);
            Assert.Equal("Int32", typeInfo.Type.Name);
 
            var thisSyntax = expr.DescendantNodes().OfType<ThisExpressionSyntax>().Single();
            var symbolInfo = speculativeModel.GetSpeculativeSymbolInfo(
                thisSyntax.SpanStart,
                thisSyntax, SpeculativeBindingOption.BindAsExpression);
            Assert.NotEqual(default, symbolInfo);
            var candidates = symbolInfo.CandidateSymbols;
            Assert.Equal(1, candidates.Length);
            Assert.IsType<ThisParameterSymbol>(candidates[0].GetSymbol());
            Assert.Equal(CandidateReason.NotReferencable, symbolInfo.CandidateReason);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForConstructorInitializer()
        {
            var source = @"class C
{
    C(int x) { }
    C() : this((int) 1) { }
}";
 
            var comp = (Compilation)CreateCompilation(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var parentModel = comp.GetSemanticModel(tree);
 
            var oldSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ConstructorInitializerSyntax>().Single();
 
            var newSyntax = SyntaxFactory.ConstructorInitializer(SyntaxKind.ThisConstructorInitializer);
 
            SemanticModel speculativeModel;
            bool success = parentModel.TryGetSpeculativeSemanticModel(oldSyntax.SpanStart, newSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var info = speculativeModel.GetSymbolInfo(newSyntax);
            var symbol = info.Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C"), symbol.ContainingType);
            Assert.Equal(SymbolKind.Method, symbol.Kind);
            var method = (IMethodSymbol)symbol;
            Assert.Equal(MethodKind.Constructor, method.MethodKind);
            Assert.Empty(method.Parameters);
 
            // test unnecessary cast removal
            var newArgument = SyntaxFactory.ParseExpression("1");
            newSyntax = oldSyntax.ReplaceNode(oldSyntax.DescendantNodes().OfType<CastExpressionSyntax>().Single(), newArgument);
 
            success = parentModel.TryGetSpeculativeSemanticModel(oldSyntax.SpanStart, newSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            info = speculativeModel.GetSymbolInfo(newSyntax);
            symbol = info.Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(comp.GlobalNamespace.GetMember<INamedTypeSymbol>("C"), symbol.ContainingType);
            Assert.Equal(SymbolKind.Method, symbol.Kind);
            method = (IMethodSymbol)symbol;
            Assert.Equal(MethodKind.Constructor, method.MethodKind);
            Assert.Equal(1, method.Parameters.Length);
 
            // test incorrect cast replacement
            newArgument = SyntaxFactory.ParseExpression("(string) 1");
            newSyntax = oldSyntax.ReplaceNode(oldSyntax.DescendantNodes().OfType<CastExpressionSyntax>().Single(), newArgument);
            success = parentModel.TryGetSpeculativeSemanticModel(oldSyntax.SpanStart, newSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            info = speculativeModel.GetSymbolInfo(newSyntax);
            symbol = info.Symbol;
            Assert.Null(symbol);
            Assert.Equal(CandidateReason.OverloadResolutionFailure, info.CandidateReason);
            Assert.Equal(2, info.CandidateSymbols.Length);
            var sortedCandidates = info.CandidateSymbols.OrderBy(s => s.ToTestDisplayString()).ToArray();
            Assert.Equal("C..ctor()", sortedCandidates[0].ToTestDisplayString());
            Assert.Equal(SymbolKind.Method, sortedCandidates[0].Kind);
            Assert.Equal("C..ctor(System.Int32 x)", sortedCandidates[1].ToTestDisplayString());
            Assert.Equal(SymbolKind.Method, sortedCandidates[1].Kind);
        }
 
        [WorkItem(545882, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545882")]
        [Fact]
        public void TestGetSpeculativeSemanticModelForConstructorInitializer_UnsupportedLocation()
        {
            var source = @"class C
{
    C() { }
}";
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var parentModel = comp.GetSemanticModel(tree);
 
            var oldSyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<ConstructorDeclarationSyntax>().Single();
 
            var newSyntax = SyntaxFactory.ConstructorInitializer(SyntaxKind.ThisConstructorInitializer);
 
            SemanticModel speculativeModel;
            bool success = parentModel.TryGetSpeculativeSemanticModel(oldSyntax.SpanStart, newSyntax, out speculativeModel);
            Assert.False(success);
            Assert.Null(speculativeModel);
        }
 
        [Fact]
        public void TestArgumentsToGetSpeculativeSemanticModelAPI()
        {
            var compilation = CreateCompilation(@"
class C 
{
  public C(): this(0) {}
  public C(int i) {}
 
  [System.Obsolete]
  void M(int x)
  {
    string y = ""Hello"";     
  }
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var ctor1 = (ConstructorDeclarationSyntax)typeDecl.Members[0];
            var ctor2 = (ConstructorDeclarationSyntax)typeDecl.Members[1];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[2];
 
            var model = compilation.GetSemanticModel(tree);
            var statement = (LocalDeclarationStatementSyntax)methodDecl.Body.Statements[0];
            var initializer = statement.Declaration.Variables[0].Initializer;
            var ctorInitializer = ctor1.Initializer;
            var attribute = methodDecl.AttributeLists[0].Attributes[0];
 
            SemanticModel speculativeModel;
            Assert.Throws<ArgumentNullException>(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, statement: null, speculativeModel: out speculativeModel));
            Assert.Throws<ArgumentNullException>(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, constructorInitializer: (ConstructorInitializerSyntax)null, speculativeModel: out speculativeModel));
            Assert.Throws<ArgumentNullException>(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, attribute: null, speculativeModel: out speculativeModel));
 
            // Speculate on a node from the same syntax tree.
            Assert.Throws<ArgumentException>(() => model.TryGetSpeculativeSemanticModel(statement.SpanStart, statement: statement, speculativeModel: out speculativeModel));
            Assert.Throws<ArgumentException>(() => model.TryGetSpeculativeSemanticModel(ctorInitializer.SpanStart, constructorInitializer: ctorInitializer, speculativeModel: out speculativeModel));
            Assert.Throws<ArgumentException>(() => model.TryGetSpeculativeSemanticModel(attribute.SpanStart, attribute: attribute, speculativeModel: out speculativeModel));
 
            // Chaining speculative semantic model is not supported.
            var speculatedStatement = statement.ReplaceNode(initializer.Value, SyntaxFactory.ParseExpression("0"));
            model.TryGetSpeculativeSemanticModel(statement.SpanStart, speculatedStatement, speculativeModel: out speculativeModel);
            Assert.Throws<InvalidOperationException>(() => speculativeModel.TryGetSpeculativeSemanticModel(speculatedStatement.SpanStart, speculatedStatement, speculativeModel: out speculativeModel));
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelOnSpeculativeSemanticModel()
        {
            var compilation = CreateCompilation(@"
class C 
{
  public C(): this(0) {}
  public C(int i) {}
 
  [System.Obsolete]
  void M(int x)
  {
    string y = ""Hello"";     
  }
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var ctor1 = (ConstructorDeclarationSyntax)typeDecl.Members[0];
            var ctor2 = (ConstructorDeclarationSyntax)typeDecl.Members[1];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[2];
 
            var model = compilation.GetSemanticModel(tree);
            var statement = (LocalDeclarationStatementSyntax)methodDecl.Body.Statements[0];
            var expression = statement.Declaration.Variables[0].Initializer.Value;
            var ctorInitializer = ctor1.Initializer;
            var attribute = methodDecl.AttributeLists[0].Attributes[0];
 
            var speculatedStatement = statement.ReplaceNode(expression, SyntaxFactory.ParseExpression("0"));
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(statement.SpanStart, speculatedStatement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            // Chaining speculative semantic model is not supported.
            // (a) Expression
            var newSpeculatedStatement = statement.ReplaceNode(expression, SyntaxFactory.ParseExpression("1.1"));
            SemanticModel newModel;
            Assert.Throws<InvalidOperationException>(() => speculativeModel.TryGetSpeculativeSemanticModel(speculatedStatement.SpanStart, newSpeculatedStatement, out newModel));
 
            // (b) Statement
            newSpeculatedStatement = (LocalDeclarationStatementSyntax)SyntaxFactory.ParseStatement(@"int z = 0;");
            Assert.Throws<InvalidOperationException>(() => speculativeModel.TryGetSpeculativeSemanticModel(speculatedStatement.SpanStart, newSpeculatedStatement, out newModel));
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelInsideUnsafeCode()
        {
            var compilation = CreateCompilation(@"
unsafe class C
{
    void M()
    {
        int x;
    }
}
");
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
 
            var model = compilation.GetSemanticModel(tree);
 
            var unsafeStatement = (LocalDeclarationStatementSyntax)SyntaxFactory.ParseStatement("int *p = &x;");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.Statements[0].Span.End, unsafeStatement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var declarator = unsafeStatement.Declaration.Variables.First();
            var initializer = declarator.Initializer.Value;
 
            var binder = ((CSharpSemanticModel)speculativeModel).GetEnclosingBinder(initializer.SpanStart);
            Assert.True(binder.InUnsafeRegion, "must be in unsafe code");
            Assert.True(binder.IsSemanticModelBinder, "must be speculative");
 
            var typeInfo = speculativeModel.GetTypeInfo(initializer);
            Assert.Equal("System.Int32*", typeInfo.Type.ToTestDisplayString());
            Assert.Equal(TypeKind.Pointer, typeInfo.Type.TypeKind);
            Assert.Equal("System.Int32*", typeInfo.ConvertedType.ToTestDisplayString());
            Assert.Equal(TypeKind.Pointer, typeInfo.ConvertedType.TypeKind);
 
            var conv = speculativeModel.GetConversion(initializer);
            Assert.Equal(ConversionKind.Identity, conv.Kind);
 
            var symbol = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.Local, symbol.Kind);
            Assert.Equal("p", symbol.Name);
        }
 
        [WorkItem(663704, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/663704")]
        [Fact]
        public void TestGetSpeculativeSemanticModelInsideUnknownAccessor()
        {
            var source = @"
class C
{
    C P
    {
        goo
        {
            return null;
        }
    }
}
";
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var accessorSyntax = tree.GetRoot().DescendantNodes().OfType<AccessorDeclarationSyntax>().Single();
            Assert.Equal(SyntaxKind.UnknownAccessorDeclaration, accessorSyntax.Kind());
 
            var statementSyntax = tree.GetRoot().DescendantNodes().OfType<ReturnStatementSyntax>().Single();
            var memberModel = ((CSharpSemanticModel)model).GetMemberModel(statementSyntax);
            Assert.Null(memberModel); // No member model since no symbol.
 
            var speculativeSyntax = SyntaxFactory.ParseStatement("return default(C);");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(statementSyntax.SpanStart, speculativeSyntax, out speculativeModel);
            Assert.False(success);
            Assert.Null(speculativeModel);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForMethodBody()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    int y = 1000;     
  }
}
");
 
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"
{ 
   int z = 0; 
   M(z);  
   M(y);    // Should generate error here as we are replacing the method body.
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            VerifySpeculativeSemanticModelForMethodBody(blockStatement, speculativeModel);
        }
 
        [Fact()]
        [WorkItem(10211, "https://github.com/dotnet/roslyn/issues/10211")]
        public void GetDependenceChainRegression_10211_working()
        {
            var compilation = CreateEmptyCompilation(@"
class Parent {}
class Child : Parent {}
");
            var semanticModel = compilation.GetSemanticModel(compilation.SyntaxTrees[0]);
            // Ensure that we don't crash here.
            semanticModel.GetMethodBodyDiagnostics();
        }
 
        [Fact()]
        [WorkItem(10211, "https://github.com/dotnet/roslyn/issues/10211")]
        public void GetDependenceChainRegression_10211()
        {
            var compilation = CreateEmptyCompilation(@"
class Child : Parent {}
class Parent {}
");
            var semanticModel = compilation.GetSemanticModel(compilation.SyntaxTrees[0]);
            // Ensure that we don't crash here.
            semanticModel.GetMethodBodyDiagnostics();
        }
 
        private static void VerifySpeculativeSemanticModelForMethodBody(BlockSyntax blockStatement, SemanticModel speculativeModel)
        {
            var localDecl = (LocalDeclarationStatementSyntax)blockStatement.Statements[0];
            var declarator = localDecl.Declaration.Variables.First();
            var local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("z", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("Int32", ((ILocalSymbol)local).Type.Name);
 
            var typeInfo = speculativeModel.GetTypeInfo(localDecl.Declaration.Type);
            Assert.NotNull(typeInfo.Type);
            Assert.Equal("Int32", typeInfo.Type.Name);
 
            var call = (InvocationExpressionSyntax)((ExpressionStatementSyntax)blockStatement.Statements[1]).Expression;
            var arg = call.ArgumentList.Arguments[0].Expression;
            var info = speculativeModel.GetSymbolInfo(arg);
            Assert.NotNull(info.Symbol);
            Assert.Equal("z", info.Symbol.Name);
            Assert.Equal(SymbolKind.Local, info.Symbol.Kind);
 
            // Shouldn't bind to local y in the original method as we are replacing the method body.
            var call2 = (InvocationExpressionSyntax)((ExpressionStatementSyntax)((BlockSyntax)blockStatement).Statements[2]).Expression;
            var arg2 = call2.ArgumentList.Arguments[0].Expression;
            var info2 = speculativeModel.GetSymbolInfo(arg2);
            Assert.Null(info2.Symbol);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForIndexerAccessorBody()
        {
            var compilation = CreateCompilation(@"
class C 
{
    private int this[int x]
    {
        set
        {
            int y = 1000;
        }
    }
}
");
 
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"
{ 
   int z = 0; 
   M(z);  
   M(y);    // Should generate error here as we are replacing the method body.
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var indexerDecl = (IndexerDeclarationSyntax)typeDecl.Members[0];
            var methodDecl = indexerDecl.AccessorList.Accessors[0];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            VerifySpeculativeSemanticModelForMethodBody(blockStatement, speculativeModel);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForPropertyAccessorBody()
        {
            var compilation = CreateCompilation(@"
class C 
{
    private int M
    {
        set
        {
            int y = 1000;
        }
    }
}
");
 
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"
{ 
   int z = 0; 
   M(z);  
   M(y);    // Should generate error here as we are replacing the method body.
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var propertyDecl = (PropertyDeclarationSyntax)typeDecl.Members[0];
            var methodDecl = propertyDecl.AccessorList.Accessors[0];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            VerifySpeculativeSemanticModelForMethodBody(blockStatement, speculativeModel);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForEventAccessorBody()
        {
            var compilation = CreateCompilation(@"
class C 
{
    private event System.Action E
    {
        add
        {
            int y = 1000;
        }
        remove
        {
        }
    }
}
");
 
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"
{ 
   int z = 0; 
   M(z);  
   M(y);    // Should generate error here as we are replacing the method body.
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var eventDecl = (EventDeclarationSyntax)typeDecl.Members[0];
            var methodDecl = eventDecl.AccessorList.Accessors[0];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            VerifySpeculativeSemanticModelForMethodBody(blockStatement, speculativeModel);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForMethodBody_DeclaredLocal()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    int y = 1000;     
  }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            // different name local
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"{ int z = 0; }");
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var declarator = ((LocalDeclarationStatementSyntax)blockStatement.Statements[0]).Declaration.Variables.First();
            var local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("z", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("Int32", ((ILocalSymbol)local).Type.Name);
 
            // same name local
            blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"{ string y = null; }");
            speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
            success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
            declarator = ((LocalDeclarationStatementSyntax)blockStatement.Statements[0]).Declaration.Variables.First();
            local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("y", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("String", ((ILocalSymbol)local).Type.Name);
 
            // parameter symbol
            blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"{ var y = x; }");
            speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
            success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
            declarator = ((LocalDeclarationStatementSyntax)blockStatement.Statements[0]).Declaration.Variables.First();
            local = speculativeModel.GetDeclaredSymbol(declarator);
            Assert.NotNull(local);
            Assert.Equal("y", local.Name);
            Assert.Equal(SymbolKind.Local, local.Kind);
            Assert.Equal("Int32", ((ILocalSymbol)local).Type.Name);
 
            var param = speculativeModel.GetSymbolInfo(declarator.Initializer.Value).Symbol;
            Assert.NotNull(param);
            Assert.Equal(SymbolKind.Parameter, param.Kind);
            var paramSymbol = (IParameterSymbol)param;
            Assert.Equal("x", paramSymbol.Name);
            Assert.Equal("Int32", paramSymbol.Type.Name);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForMethodBody_GetDeclaredLabelSymbol()
        {
            var compilation = CreateCompilation(@"
class C 
{
  void M(int x)
  {
    int y = 1000;     
  }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"{ label: y++; }");
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
            var labeledStatement = blockStatement.Statements[0];
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var label = speculativeModel.GetDeclaredSymbol(labeledStatement);
            Assert.NotNull(label);
            Assert.Equal("label", label.Name);
            Assert.Equal(SymbolKind.Label, label.Kind);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForMethodBody_GetDeclaredLambdaParameterSymbol()
        {
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(@"
using System.Linq;
 
class C 
{
  void M(int x)
  {
    int z = 0;
  }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"{ Func<int, int> var = (z) => x + z; }");
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].Span.End, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var lambdaExpression = blockStatement.Statements[0].DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().FirstOrDefault();
            var lambdaParam = lambdaExpression.ParameterList.Parameters[0];
            var parameterSymbol = speculativeModel.GetDeclaredSymbol(lambdaParam);
            Assert.NotNull(parameterSymbol);
            Assert.Equal("z", parameterSymbol.Name);
        }
 
        private static void TestGetSpeculativeSemanticModelForTypeSyntax_Common(
            SemanticModel model,
            int position,
            TypeSyntax speculatedTypeSyntax,
            SpeculativeBindingOption bindingOption,
            SymbolKind expectedSymbolKind,
            string expectedTypeDisplayString)
        {
            Assert.False(model.IsSpeculativeSemanticModel);
            Assert.Null(model.ParentModel);
            Assert.Equal(0, model.OriginalPositionForSpeculation);
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, speculatedTypeSyntax, out speculativeModel, bindingOption);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
            Assert.False(speculativeModel.IgnoresAccessibility);
 
            Assert.True(speculativeModel.IsSpeculativeSemanticModel);
            Assert.Equal(model, speculativeModel.ParentModel);
            Assert.NotNull(speculativeModel);
            Assert.Equal(position, speculativeModel.OriginalPositionForSpeculation);
 
            var symbol = speculativeModel.GetSymbolInfo(speculatedTypeSyntax).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(expectedSymbolKind, symbol.Kind);
            Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString());
 
            var typeSymbol = speculativeModel.GetTypeInfo(speculatedTypeSyntax).Type;
            Assert.NotNull(symbol);
            Assert.Equal(expectedSymbolKind, symbol.Kind);
            Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString());
 
            if (speculatedTypeSyntax.Kind() == SyntaxKind.QualifiedName)
            {
                var right = ((QualifiedNameSyntax)speculatedTypeSyntax).Right;
 
                symbol = speculativeModel.GetSymbolInfo(right).Symbol;
                Assert.NotNull(symbol);
                Assert.Equal(expectedSymbolKind, symbol.Kind);
                Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString());
 
                typeSymbol = speculativeModel.GetTypeInfo(right).Type;
                Assert.NotNull(symbol);
                Assert.Equal(expectedSymbolKind, symbol.Kind);
                Assert.Equal(expectedTypeDisplayString, symbol.ToDisplayString());
            }
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForMethodBody_SwitchStatement()
        {
            var compilation = CreateCompilation(@"
using System;
 
class C 
{
  void M(int x)
  {
    switch(x)
    {
        case 0:
            Console.WriteLine(x);
            break;
    }
  }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"{
    switch(x)
    {
        case 1:
            Console.WriteLine(x);
            break;
    }
}");
 
            var speculatedMethod = methodDecl.ReplaceNode(methodDecl.Body, blockStatement);
            blockStatement = speculatedMethod.Body;
            var switchStatement = (SwitchStatementSyntax)blockStatement.Statements[0];
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModelForMethodBody(methodDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var switchLabel = switchStatement.Sections[0].Labels[0] as CaseSwitchLabelSyntax;
            Assert.NotNull(switchLabel);
            var constantVal = speculativeModel.GetConstantValue(switchLabel.Value);
            Assert.True(constantVal.HasValue);
            Assert.Equal(1, constantVal.Value);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForTypeSyntax_InGlobalUsing()
        {
            var compilation = CreateCompilation(@"using System.Runtime;");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var usingStatement = root.Usings[0];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedUsingExpression = SyntaxFactory.ParseName("System.Collections");
            TestGetSpeculativeSemanticModelForTypeSyntax_Common(model, usingStatement.Name.Position,
                speculatedUsingExpression, SpeculativeBindingOption.BindAsTypeOrNamespace, SymbolKind.Namespace, "System.Collections");
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForTypeSyntax_InGlobalAlias()
        {
            var compilation = CreateCompilation(@"using A = System.Exception;");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var usingStatement = root.Usings[0];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedUsingExpression = SyntaxFactory.ParseName("System.ArgumentException");
            TestGetSpeculativeSemanticModelForTypeSyntax_Common(model, usingStatement.Name.Position,
                speculatedUsingExpression, SpeculativeBindingOption.BindAsExpression, SymbolKind.NamedType, "System.ArgumentException");
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForTypeSyntax_InBaseList()
        {
            var compilation = CreateCompilation(@"
class MyException : System.Exception
{
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var baseList = typeDecl.BaseList;
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedTypeExpression = SyntaxFactory.ParseName("System.ArgumentException");
            TestGetSpeculativeSemanticModelForTypeSyntax_Common(model, baseList.SpanStart,
                speculatedTypeExpression, SpeculativeBindingOption.BindAsTypeOrNamespace, SymbolKind.NamedType, "System.ArgumentException");
 
            model = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
            SemanticModel speculativeModel;
            model.TryGetSpeculativeSemanticModel(baseList.SpanStart, speculatedTypeExpression, out speculativeModel);
            Assert.True(speculativeModel.IgnoresAccessibility);
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForTypeSyntax_InMemberDeclaration()
        {
            var compilation = CreateCompilation(@"
class Program
{
    System.Exception field = null;
    System.Exception Method(System.Exception param)
    {
        return field;
    }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var fieldDecl = (FieldDeclarationSyntax)typeDecl.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[1];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedTypeExpression = SyntaxFactory.ParseName("System.ArgumentException");
            TestGetSpeculativeSemanticModelForTypeSyntax_Common(model, fieldDecl.SpanStart,
                speculatedTypeExpression, SpeculativeBindingOption.BindAsTypeOrNamespace, SymbolKind.NamedType, "System.ArgumentException");
 
            TestGetSpeculativeSemanticModelForTypeSyntax_Common(model, methodDecl.ReturnType.SpanStart,
                speculatedTypeExpression, SpeculativeBindingOption.BindAsTypeOrNamespace, SymbolKind.NamedType, "System.ArgumentException");
 
            TestGetSpeculativeSemanticModelForTypeSyntax_Common(model, methodDecl.ParameterList.Parameters.First().SpanStart,
                speculatedTypeExpression, SpeculativeBindingOption.BindAsTypeOrNamespace, SymbolKind.NamedType, "System.ArgumentException");
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForTypeSyntax_AliasName()
        {
            var compilation = CreateCompilation(@"
using A = System.ArgumentException;
 
class Program
{
    System.Exception field = null;
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var fieldDecl = (FieldDeclarationSyntax)typeDecl.Members[0];
            var model = compilation.GetSemanticModel(tree);
 
            var speculatedAliasName = SyntaxFactory.ParseName("A");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(fieldDecl.SpanStart, speculatedAliasName, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var symbol = speculativeModel.GetAliasInfo(speculatedAliasName);
            Assert.NotNull(symbol);
            Assert.Equal("A", symbol.ToDisplayString());
            Assert.Equal("System.ArgumentException", symbol.Target.ToDisplayString());
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForTypeCrefSyntax()
        {
            var compilation = CreateCompilationWithMscorlib40AndDocumentationComments(@"
/// <summary>
/// <see cref=""int""/>
/// </summary>
class A { }
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var cref = typeDecl.DescendantNodes(descendIntoTrivia: true).OfType<TypeCrefSyntax>().Single();
 
            var model = (CSharpSemanticModel)compilation.GetSemanticModel(tree);
            var symbol = model.GetSymbolInfo(cref.Type).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal("int", symbol.ToDisplayString());
 
            var speculatedCref = (TypeCrefSyntax)SyntaxFactory.ParseCref("object");
 
            // TryGetSpeculativeSemanticModel
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(cref.SpanStart, speculatedCref, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            symbol = speculativeModel.GetSymbolInfo(speculatedCref.Type).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("object", symbol.ToDisplayString());
 
            // GetSpeculativeSymbolInfo
            symbol = model.GetSpeculativeSymbolInfo(cref.SpanStart, speculatedCref).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("object", symbol.ToDisplayString());
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForNameMemberCrefSyntax()
        {
            var compilation = CreateCompilationWithMscorlib40AndDocumentationComments(@"
/// <summary>
/// <see cref=""int""/>
/// </summary>
class A { }
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var cref = typeDecl.DescendantNodes(descendIntoTrivia: true).OfType<TypeCrefSyntax>().Single();
 
            var model = (CSharpSemanticModel)compilation.GetSemanticModel(tree);
            var symbol = model.GetSymbolInfo(cref.Type).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal("int", symbol.ToDisplayString());
 
            var speculatedCref = (NameMemberCrefSyntax)SyntaxFactory.ParseCref("A");
 
            // TryGetSpeculativeSemanticModel
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(cref.SpanStart, speculatedCref, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            symbol = speculativeModel.GetSymbolInfo(speculatedCref.Name).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("A", symbol.ToDisplayString());
 
            // GetSpeculativeSymbolInfo
            symbol = model.GetSpeculativeSymbolInfo(cref.SpanStart, speculatedCref).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("A", symbol.ToDisplayString());
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForQualifiedCrefSyntax()
        {
            var compilation = CreateCompilationWithMscorlib40AndDocumentationComments(@"
/// <summary>
/// <see cref=""int""/>
/// </summary>
class A
{
    class B { }
 
    static void M() { }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var cref = typeDecl.DescendantNodes(descendIntoTrivia: true).OfType<TypeCrefSyntax>().Single();
 
            var model = (CSharpSemanticModel)compilation.GetSemanticModel(tree);
            var symbol = model.GetSymbolInfo(cref.Type).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal("int", symbol.ToDisplayString());
 
            var speculatedCref = (QualifiedCrefSyntax)SyntaxFactory.ParseCref("A.B");
 
            // Type member: TryGetSpeculativeSemanticModel
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(cref.SpanStart, speculatedCref, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            symbol = speculativeModel.GetSymbolInfo(speculatedCref).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("A.B", symbol.ToDisplayString());
 
            symbol = speculativeModel.GetSymbolInfo(speculatedCref.Member).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("A.B", symbol.ToDisplayString());
 
            symbol = speculativeModel.GetTypeInfo(speculatedCref.Container).Type;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("A", symbol.ToDisplayString());
 
            // Type member: GetSpeculativeSymbolInfo
            symbol = model.GetSpeculativeSymbolInfo(cref.SpanStart, speculatedCref).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("A.B", symbol.ToDisplayString());
 
            // Method member: TryGetSpeculativeSemanticModel
            speculatedCref = (QualifiedCrefSyntax)SyntaxFactory.ParseCref("A.M");
 
            success = model.TryGetSpeculativeSemanticModel(cref.SpanStart, speculatedCref, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            symbol = speculativeModel.GetSymbolInfo(speculatedCref).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.Method, symbol.Kind);
            Assert.Equal("A.M()", symbol.ToDisplayString());
 
            symbol = speculativeModel.GetSymbolInfo(speculatedCref.Member).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.Method, symbol.Kind);
            Assert.Equal("A.M()", symbol.ToDisplayString());
 
            symbol = speculativeModel.GetTypeInfo(speculatedCref.Container).Type;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.NamedType, symbol.Kind);
            Assert.Equal("A", symbol.ToDisplayString());
 
            // Method member: GetSpeculativeSymbolInfo
            symbol = model.GetSpeculativeSymbolInfo(cref.SpanStart, speculatedCref).Symbol;
            Assert.NotNull(symbol);
            Assert.Equal(SymbolKind.Method, symbol.Kind);
            Assert.Equal("A.M()", symbol.ToDisplayString());
        }
 
        [Fact]
        public void TestGetSpeculativeSemanticModelForCrefSyntax_InvalidPosition()
        {
            var compilation = CreateCompilationWithMscorlib40AndDocumentationComments(@"
/// <summary>
/// <see cref=""int""/>
/// </summary>
class A
{
    static void M() { }
}
");
 
            var tree = compilation.SyntaxTrees[0];
            var root = tree.GetCompilationUnitRoot();
            var typeDecl = (TypeDeclarationSyntax)root.Members[0];
            var methodDecl = (MethodDeclarationSyntax)typeDecl.Members[0];
            var model = (CSharpSemanticModel)compilation.GetSemanticModel(tree);
 
            var speculatedCref = (TypeCrefSyntax)SyntaxFactory.ParseCref("object");
 
            // TryGetSpeculativeSemanticModel
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(typeDecl.SpanStart, speculatedCref, out speculativeModel);
            Assert.False(success);
 
            success = model.TryGetSpeculativeSemanticModel(methodDecl.Body.SpanStart, speculatedCref, out speculativeModel);
            Assert.False(success);
 
            // GetSpeculativeSymbolInfo
            var symbolInfo = model.GetSpeculativeSymbolInfo(methodDecl.Body.SpanStart, speculatedCref);
            Assert.Null(symbolInfo.Symbol);
        }
 
        [WorkItem(731108, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/731108")]
        [Fact]
        public void Repro731108()
        {
            var source = @"
public class C
{
    static void Main()
    {
        M(async x => x);
    }
 
    static void M(C c)
    {
    }
}
";
 
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var syntax = tree.GetRoot().DescendantNodes().OfType<SimpleLambdaExpressionSyntax>().Single().
                Body.DescendantNodesAndSelf().OfType<IdentifierNameSyntax>().Single();
            Assert.Equal("x", syntax.Identifier.ValueText);
 
            var symbol = model.GetSymbolInfo(syntax).Symbol;
            Assert.Equal(SymbolKind.Parameter, symbol.Kind);
            Assert.Equal("x", symbol.Name);
            Assert.Equal(TypeKind.Error, ((IParameterSymbol)symbol).Type.TypeKind);
        }
 
        [WorkItem(783566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/783566")]
        [Fact]
        public void SpeculateAboutYieldStatement1()
        {
            var source = @"
class C
{
    void M() // No way to infer iterator element type.
    {
        return;
    }
}
";
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var position = source.IndexOf("return", StringComparison.Ordinal);
            var yieldStatement = (YieldStatementSyntax)SyntaxFactory.ParseStatement("yield return 1;");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, yieldStatement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var info = speculativeModel.GetTypeInfo(yieldStatement.Expression);
            Assert.Equal(SpecialType.System_Int32, info.Type.SpecialType);
            Assert.Equal(TypeKind.Error, info.ConvertedType.TypeKind);
        }
 
        [WorkItem(783566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/783566")]
        [Fact]
        public void SpeculateAboutYieldStatement2()
        {
            var source = @"
using System.Collections.Generic;
 
class C
{
    IEnumerable<long> M() // Can infer iterator element type.
    {
        return null;
    }
}
";
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var position = source.IndexOf("return", StringComparison.Ordinal);
            var yieldStatement = (YieldStatementSyntax)SyntaxFactory.ParseStatement("yield return 1;");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, yieldStatement, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var info = speculativeModel.GetTypeInfo(yieldStatement.Expression);
            Assert.Equal(SpecialType.System_Int32, info.Type.SpecialType);
            Assert.Equal(SpecialType.System_Int64, info.ConvertedType.SpecialType);
        }
 
        [WorkItem(791794, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/791794")]
        [Fact]
        public void SpeculateAboutOmittedArraySizeInCref()
        {
            var source = @"
/// <see cref=""int""/>
class C
{
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var position = source.IndexOf("int", StringComparison.Ordinal);
            var typeSyntax = SyntaxFactory.ParseTypeName("System.Collections.Generic.IEnumerable<C[]>");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, typeSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var omittedArraySize = typeSyntax.DescendantNodes().OfType<OmittedArraySizeExpressionSyntax>().Single();
            var info = speculativeModel.GetSymbolInfo(omittedArraySize); // Used to throw NRE.
            Assert.Null(info.Symbol);
            Assert.Equal(CandidateReason.None, info.CandidateReason);
            Assert.Equal(0, info.CandidateSymbols.Length);
        }
 
        [WorkItem(14384, "https://github.com/dotnet/roslyn/issues/14384")]
        [Fact]
        public void SpeculateWithExpressionVariables_out()
        {
            var source = @"
class C
{
    void M()
    {
        int x;
        TakesOut(out x);
    }
    void TakesOut(out int x) { x = 0; }
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var method1 = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info1 = model.GetSymbolInfo(method1);
            Assert.NotNull(info1.Symbol);
 
            var position = source.IndexOf("TakesOut", StringComparison.Ordinal);
            var statementSyntax = SyntaxFactory.ParseStatement("TakesOut(out int x);");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, statementSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var method2 = statementSyntax.DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info2 = speculativeModel.GetSymbolInfo(method2);
            Assert.NotNull(info2.Symbol);
 
            Assert.Equal(info1.Symbol, info2.Symbol);
        }
 
        [WorkItem(14384, "https://github.com/dotnet/roslyn/issues/14384")]
        [Fact]
        public void SpeculateWithExpressionVariables_out2()
        {
            var source = @"
class C
{
    void M()
    {
        int y;
        TakesOut(out y);
    }
    void TakesOut(out int y) { y = 0; }
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var method1 = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info1 = model.GetSymbolInfo(method1);
            Assert.NotNull(info1.Symbol);
 
            var position = source.IndexOf("TakesOut", StringComparison.Ordinal);
            var statementSyntax = SyntaxFactory.ParseStatement("TakesOut(out int x);");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, statementSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var method2 = statementSyntax.DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info2 = speculativeModel.GetSymbolInfo(method2);
            Assert.NotNull(info2.Symbol);
 
            Assert.Equal(info1.Symbol, info2.Symbol);
        }
 
        [WorkItem(14384, "https://github.com/dotnet/roslyn/issues/14384")]
        [Fact]
        public void SpeculateWithExpressionVariables_out3()
        {
            var source = @"
class C
{
    void M()
    {
        int x;
        TakesOut(out x);
    }
    void TakesOut(out int x) { x = 0; }
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var method1 = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info1 = model.GetSymbolInfo(method1);
            Assert.NotNull(info1.Symbol);
 
            var position = source.IndexOf("TakesOut", StringComparison.Ordinal);
            var statementSyntax = SyntaxFactory.ParseExpression("TakesOut(out int x)");
            var info2 = model.GetSpeculativeSymbolInfo(position, statementSyntax, SpeculativeBindingOption.BindAsExpression);
            Assert.NotNull(info2.Symbol);
 
            Assert.Equal(info1.Symbol, info2.Symbol);
        }
 
        [WorkItem(14384, "https://github.com/dotnet/roslyn/issues/14384")]
        [Fact]
        public void SpeculateWithExpressionVariables_out4()
        {
            var source = @"
class C
{
    void M()
    {
        int y;
        TakesOut(out y);
    }
    void TakesOut(out int y) { y = 0; }
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var method1 = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info1 = model.GetSymbolInfo(method1);
            Assert.NotNull(info1.Symbol);
 
            var position = source.IndexOf("TakesOut", StringComparison.Ordinal);
            var statementSyntax = SyntaxFactory.ParseStatement("{ TakesOut(out int x); }");
            statementSyntax = ((BlockSyntax)statementSyntax).Statements[0];
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, statementSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var method2 = statementSyntax.DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info2 = speculativeModel.GetSymbolInfo(method2);
            Assert.NotNull(info2.Symbol);
 
            Assert.Equal(info1.Symbol, info2.Symbol);
        }
 
        [WorkItem(14384, "https://github.com/dotnet/roslyn/issues/14384")]
        [Fact]
        public void SpeculateWithExpressionVariables_pattern()
        {
            var source = @"
class C
{
    void M(object o)
    {
        Method(o is string);
        string s = o as string;
    }
    bool Method(bool b) => b;
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var method1 = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info1 = model.GetSymbolInfo(method1);
            Assert.NotNull(info1.Symbol);
 
            var position = source.IndexOf("Method", StringComparison.Ordinal);
            var statementSyntax = SyntaxFactory.ParseStatement("Method(o is string s);");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, statementSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var method2 = statementSyntax.DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info2 = speculativeModel.GetSymbolInfo(method2);
            Assert.NotNull(info2.Symbol);
 
            Assert.Equal(info1.Symbol, info2.Symbol);
        }
 
        [WorkItem(14384, "https://github.com/dotnet/roslyn/issues/14384")]
        [Fact]
        public void SpeculateWithExpressionVariables_pattern2()
        {
            var source = @"
class C
{
    void M(object o)
    {
        Method(o is string);
        string s2 = o as string;
    }
    bool Method(bool b) => b;
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var method1 = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info1 = model.GetSymbolInfo(method1);
            Assert.NotNull(info1.Symbol);
 
            var position = source.IndexOf("Method", StringComparison.Ordinal);
            var statementSyntax = SyntaxFactory.ParseStatement("Method(o is string s);");
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, statementSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var method2 = statementSyntax.DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info2 = speculativeModel.GetSymbolInfo(method2);
            Assert.NotNull(info2.Symbol);
 
            Assert.Equal(info1.Symbol, info2.Symbol);
        }
 
        [WorkItem(14384, "https://github.com/dotnet/roslyn/issues/14384")]
        [Fact]
        public void SpeculateWithExpressionVariables_pattern3()
        {
            var source = @"
class C
{
    void M(object o)
    {
        Method(o is string);
        string s2 = o as string;
    }
    bool Method(bool b) => b;
}
";
 
            var comp = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var method1 = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single().Expression;
            var info1 = model.GetSymbolInfo(method1);
            Assert.NotNull(info1.Symbol);
 
            var position = source.IndexOf("Method", StringComparison.Ordinal);
            var statementSyntax = SyntaxFactory.ParseExpression("Method(o is string s)");
            var info2 = model.GetSpeculativeSymbolInfo(position, statementSyntax, SpeculativeBindingOption.BindAsExpression);
            Assert.NotNull(info2.Symbol);
 
            Assert.Equal(info1.Symbol, info2.Symbol);
        }
 
        [Fact]
        public void BindSpeculativeAttributeWithExpressionVariable_1()
        {
            new ObsoleteAttribute("goo");
 
            var source =
@"using System;
class C { }";
            var compilation = CreateCompilation(source);
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var position = tree.GetText().ToString().IndexOf("class C {", StringComparison.Ordinal);
            var attr2 = ParseAttributeSyntax("[ObsoleteAttribute(string.Empty is string s ? s : string.Empty)]");
 
            var symbolInfo = model.GetSpeculativeSymbolInfo(position, attr2);
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Equal("System.ObsoleteAttribute..ctor(System.String message)", symbolInfo.Symbol.ToTestDisplayString());
        }
 
        [Fact]
        public void BindSpeculativeAttributeWithExpressionVariable_2()
        {
            new ObsoleteAttribute("goo");
 
            var source =
@"using System;
class C { }";
            var compilation = CreateCompilation(source);
 
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
 
            var position = tree.GetText().ToString().IndexOf("class C {", StringComparison.Ordinal);
            var attr2 = ParseAttributeSyntax("[ObsoleteAttribute(string.Empty is string s ? s : string.Empty)]");
            SemanticModel model2;
            model.TryGetSpeculativeSemanticModel(position, attr2, out model2);
 
            var symbolInfo = model2.GetSymbolInfo(attr2);
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Equal("System.ObsoleteAttribute..ctor(System.String message)", symbolInfo.Symbol.ToTestDisplayString());
        }
 
        private AttributeSyntax ParseAttributeSyntax(string source)
        {
            return SyntaxFactory.ParseCompilationUnit(source + " class X {}").Members.First().AsTypeDeclarationSyntax().AttributeLists.First().Attributes.First();
        }
 
        [WorkItem(784255, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/784255")]
        [Fact]
        public void Repro784255()
        {
            var source = @"
using System;
 
public class CategoryAttribute : Attribute
{
    public CategoryAttribute(string s) { }
    private CategoryAttribute() { }
}
 
struct S
{
}
";
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var position = source.IndexOf("struct", StringComparison.Ordinal);
            var attributeSyntax = SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("Category"));
 
            SemanticModel speculativeModel;
            var success = model.TryGetSpeculativeSemanticModel(position, attributeSyntax, out speculativeModel);
            Assert.True(success);
            Assert.NotNull(speculativeModel);
 
            var info = speculativeModel.GetSymbolInfo(attributeSyntax.Name);
        }
 
        [WorkItem(1015557, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1015557")]
        [Fact(Skip = "1015557")]
        public void GetSpeculativeSymbolInfoForGenericNameInCref()
        {
            var tree = CSharpSyntaxTree.ParseText(@"using System.Collections.Generic;
class Program
{
    /// <summary>
    /// <see cref=""System.Collections.Generic.List{T}.Contains(T)""/>
    /// </summary>
    static void Main()
    {
    }
}", CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose));
            var compilation = CreateCompilation(tree);
            var root = tree.GetCompilationUnitRoot();
            var crefSyntax = root.DescendantNodes(descendIntoTrivia: true).OfType<QualifiedCrefSyntax>().Single();
            var semanticModel = compilation.GetSemanticModel(tree);
 
            var symbolInfo = semanticModel.GetSymbolInfo(crefSyntax.FindNode(new TextSpan(91, 34)));
            var oldSymbol = symbolInfo.Symbol;
            Assert.NotNull(oldSymbol);
            Assert.Equal(SymbolKind.NamedType, oldSymbol.Kind);
            Assert.Equal("System.Collections.Generic.List<T>", oldSymbol.ToTestDisplayString());
 
            var speculatedName = (GenericNameSyntax)SyntaxFactory.GenericName("List{T}");
            var speculativeSymbolInfo = semanticModel.GetSpeculativeSymbolInfo(crefSyntax.SpanStart, speculatedName, SpeculativeBindingOption.BindAsExpression);
            var newSymbol = speculativeSymbolInfo.Symbol;
            Assert.NotNull(newSymbol);
            Assert.Equal(SymbolKind.NamedType, newSymbol.Kind);
            Assert.Equal("System.Collections.Generic.List<T>", newSymbol.ToTestDisplayString());
 
            Assert.False(((NamedTypeSymbol)newSymbol).TypeArguments().Single().IsErrorType());
            Assert.True(newSymbol.Equals(oldSymbol));
        }
 
        [WorkItem(823791, "DevDiv")]
        [Fact]
        public void LambdaArgumentInBadCall_Constructor()
        {
            var source = @"
using System;
 
class Test
{
    void M()
    {
        new Test(s => s.
    }
 
    Test(Action<string> a, int i) { }
}
";
            CheckLambdaArgumentInBadCall(source);
        }
 
        [WorkItem(823791, "DevDiv")]
        [Fact]
        public void LambdaArgumentInBadCall_Method()
        {
            var source = @"
using System;
 
class Test
{
    void M()
    {
        Method(s => s.
    }
 
    void Method(Action<string> a, int i) { }
}
";
            CheckLambdaArgumentInBadCall(source);
        }
 
        [WorkItem(823791, "DevDiv")]
        [Fact]
        public void LambdaArgumentInBadCall_Indexer()
        {
            var source = @"
using System;
 
class Test
{
    void M()
    {
        var t = this[s => s.
    }
 
    int this[Action<string> a, int i] { get { return 0; } }
}
";
            CheckLambdaArgumentInBadCall(source);
        }
 
        [WorkItem(823791, "DevDiv")]
        [Fact]
        public void LambdaArgumentInBadCall_Delegate()
        {
            var source = @"
using System;
 
class Test
{
    void M()
    {
        d(s => s.
    }
 
    Action<Action<string>, int> d = null;
}
";
            CheckLambdaArgumentInBadCall(source);
        }
 
        [WorkItem(823791, "DevDiv")]
        [Fact]
        public void LambdaArgumentInBadCall_ConstructorInitializer()
        {
            var source = @"
using System;
 
class Test
{
    protected Test(Action<string> a, int i) { }
}
 
class Derived : Test
{
    Derived()
        : base(s => s.
    {
    }
}
";
            CheckLambdaArgumentInBadCall(source);
        }
 
        private static void CheckLambdaArgumentInBadCall(string source)
        {
            var comp = (Compilation)CreateCompilation(source);
 
            var tree = comp.SyntaxTrees.Single();
            Assert.NotEmpty(tree.GetDiagnostics());
 
            var memberAccess = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().Single();
            var identifier = (IdentifierNameSyntax)memberAccess.Expression;
            Assert.Equal("s", identifier.Identifier.ValueText);
 
            var stringType = comp.GetSpecialType(SpecialType.System_String);
            var actionType = comp.GetWellKnownType(WellKnownType.System_Action_T).Construct(stringType);
 
            var model = comp.GetSemanticModel(tree);
 
            // Can't walk up to ArgumentListSyntax because indexers use BracketedArgumentListSyntax.
            var expr = identifier.FirstAncestorOrSelf<ArgumentSyntax>().Parent.Parent;
 
            var exprInfo = model.GetSymbolInfo(expr);
            var firstParamType = ((ISymbol)exprInfo.CandidateSymbols.Single()).GetParameters().First().Type;
            Assert.Equal(actionType, firstParamType);
 
            var identifierInfo = model.GetTypeInfo(identifier);
            Assert.Equal(stringType, identifierInfo.Type);
            Assert.Equal(stringType, identifierInfo.ConvertedType);
        }
 
        [Fact, WorkItem(45825, "https://github.com/dotnet/roslyn/issues/45825")]
        public void LambdaReturnSpeculation()
        {
            var comp = CreateCompilation(@"
class C
{
    public static implicit operator C(string s) => null!;
    C M()
    {
        string s = """";
        System.Func<string> local = () =>
        {
            s.ToString();
            return s;
        };
        local();
        return null!;
    }
}");
            comp.VerifyDiagnostics(
            );
            var tree = comp.SyntaxTrees[0];
            var model = comp.GetSemanticModel(tree);
            var localFunctionBody = tree.GetRoot().DescendantNodes().OfType<LambdaExpressionSyntax>().Single();
            var typeInfo = model.GetTypeInfo(localFunctionBody.DescendantNodes().OfType<ReturnStatementSyntax>().Single().Expression!);
            Assert.Equal("System.String", typeInfo.ConvertedType.ToTestDisplayString(includeNonNullable: false));
            var @return = (ReturnStatementSyntax)SyntaxFactory.ParseStatement("return s;");
            Assert.True(model.TryGetSpeculativeSemanticModel(localFunctionBody.Block!.Statements[0].SpanStart + 1, @return, out var specModel));
            typeInfo = specModel!.GetTypeInfo(@return.Expression!);
 
            // This behavior is broken. The return type here should be 'System.String' because we are speculating within the lambda.
            // https://github.com/dotnet/roslyn/issues/45825
            Assert.Equal("C", typeInfo.ConvertedType.ToTestDisplayString(includeNonNullable: false));
        }
 
        [WorkItem(850907, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/850907")]
        [Fact]
        public void ExtensionMethodViability()
        {
            var source = @"
static class Extensions
{
    private static void ToString(this object o, int x)
    {
        o.ToString(1);
    }
}
";
 
            var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
            comp.VerifyDiagnostics();
 
            var extensionMethod = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Extensions").GetMember<MethodSymbol>("ToString");
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var callSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
 
            var memberGroup = model.GetMemberGroup(callSyntax.Expression);
            Assert.Contains(extensionMethod.ReduceExtensionMethod().ISymbol, memberGroup);
        }
 
        [WorkItem(849698, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/849698")]
        [Fact]
        public void LookupExternAlias()
        {
            var source = @"
extern alias Alias;
 
class C
{
    static void Main()
    {
        Alias::C.M(); 
    }
 
";
 
            var libRef = CreateCompilation("", assemblyName: "lib").EmitToImageReference(aliases: ImmutableArray.Create("Alias"));
            var comp = CreateCompilation(source, new[] { libRef });
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var syntax = tree.GetRoot().DescendantNodes().OfType<AliasQualifiedNameSyntax>().Single();
 
            var symbol = model.LookupSymbols(syntax.SpanStart, name: "Alias").Single();
            Assert.Equal("Alias", symbol.Name);
            Assert.Equal(SymbolKind.Alias, symbol.Kind);
 
            var target = (INamespaceSymbol)((IAliasSymbol)symbol).Target;
            Assert.True(target.IsGlobalNamespace);
            Assert.Equal("lib", target.ContainingAssembly.Name);
        }
 
        [Theory, MemberData(nameof(FileScopedOrBracedNamespace))]
        public void LookupInNamespace(string ob, string cb)
        {
            var source = @"
namespace NS
" + ob + @"
    class C
    {
        void M() { }
        void M0() { }
    }
" + cb + @"
";
            var comp = CreateCompilation(source);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
            var methodDecl = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
            var endPosition = methodDecl.Body.OpenBraceToken.EndPosition;
            var symbol = model.LookupSymbols(endPosition, name: "M0").Single();
            Assert.Equal("void NS.C.M0()", symbol.ToTestDisplayString());
        }
 
        [WorkItem(1019366, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1019366")]
        [WorkItem(273, "CodePlex")]
        [ClrOnlyFact]
        public void Bug1019366()
        {
            var source = @"
using System;
 
static class Program
{
    static void Main()
    {
        short case1 = unchecked((short)65535.17567);
        Console.WriteLine(case1);
        int? case2 = (int?)5.5;
        Console.WriteLine(case2);
        int? case3 = (int?)5;
        Console.WriteLine(case3);
    }
}
";
 
            var comp = (Compilation)CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            // The CodePlex bug indicates that this should return a constant value of -1.  However, the specified
            // value of this is explicitly "undefined", and differs from one host architecture to another.
            // For determinism we make all undefined unchecked floating to integral conversions yield zero
            // at compile-time.  That may differ from the result at runtime depending on your runtime architecture.
            // See https://github.com/dotnet/roslyn/issues/37527
            var method = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Single();
            var init0 = method.Body.Statements[0].DescendantNodes().OfType<VariableDeclaratorSyntax>().Single().Initializer.Value;
            var value0 = model.GetConstantValue(init0);
            var typeInfo0 = model.GetTypeInfo(init0);
            Assert.True(value0.HasValue);
            Assert.Equal(0, (short)value0.Value);
            Assert.True(typeInfo0.Type != null && typeInfo0.Type.SpecialType == SpecialType.System_Int16);
 
            // The CodePlex bug indicates this should return a constant value of 5.  While 'case2' should 
            // have that value it is not constant because of the nullable cast
            var init1 = method.Body.Statements[2].DescendantNodes().OfType<VariableDeclaratorSyntax>().Single().Initializer.Value;
            var value1 = model.GetConstantValue(init1);
            var typeInfo1 = model.GetTypeInfo(init1);
            var type1 = comp.GetSpecialType(SpecialType.System_Nullable_T).Construct(comp.GetSpecialType(SpecialType.System_Int32));
            Assert.False(value1.HasValue);
            Assert.True(typeInfo1.Type != null && typeInfo1.Type.Equals(type1));
 
            var init2 = method.Body.Statements[4].DescendantNodes().OfType<VariableDeclaratorSyntax>().Single().Initializer.Value;
            var value2 = model.GetConstantValue(init2);
            var typeInfo2 = model.GetTypeInfo(init2);
            var type2 = comp.GetSpecialType(SpecialType.System_Nullable_T).Construct(comp.GetSpecialType(SpecialType.System_Int32));
            Assert.False(value2.HasValue);
            Assert.True(typeInfo2.Type != null && typeInfo2.Type.Equals(type2));
 
            var output = @"
0
5
5";
            CompileAndVerify(compilation: comp, expectedOutput: output);
        }
 
        [Fact]
        public void Regression01()
        {
            Regression(@"
using System;
 
class MyClass {
 
	public protected int intI = 1;
 
	public static int Main() {
		return 1;
	}
}"
                );
        }
 
        [Fact]
        public void Regression02()
        {
            Regression(@"
using System;
 
class Convert
{
	public static void Main()
	{
		S s = new S();
	}
}
"
                );
        }
 
        [Fact]
        public void Regression03()
        {
            Regression(@"
using System;
 
namespace Microsoft.Conformance.Expressions
{
    using basic097LevelOne.basic097LevelTwo;
 
    public class basic097I<A1>
    {
        public static int Method()
        {
            return 0;
        }
    }
 
    namespace basic097LevelOne
    {
        namespace basic097LevelTwo
        {
            public class basic097I<A1>
            {
            }
        }
    } 
}"
                );
        }
 
        [Fact, WorkItem(1504, "https://github.com/dotnet/roslyn/issues/1504")]
        public void ContainingSymbol02()
        {
            var source =
@"using System;
class C
{
    static bool G<T>(Func<T> f) => true;
    static void F()
    {
        Exception x1 = null;
        try
        {
            G(() => x1);
        }
        catch (Exception x2) when (G(() => x2))
        {
        }
    }
}";
 
            var compilation = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            var model = compilation.GetSemanticModel(compilation.SyntaxTrees.Single());
            for (var match = System.Text.RegularExpressions.Regex.Match(source, " => x"); match.Success; match = match.NextMatch())
            {
                var discarded = model.GetEnclosingSymbol(match.Index);
            }
        }
 
        [Fact, WorkItem(1504, "https://github.com/dotnet/roslyn/issues/1504")]
        public void ContainingSymbol03()
        {
            var source =
@"using System;
class C
{
    static bool G<T>(Func<T> f) => true;
    static void F()
    {
        Exception x1 = null, x2 = null;
        do
        {
            G(() => x1);
        }
        while (G(() => x2));
    }
}";
 
            var compilation = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            var tree = compilation.SyntaxTrees.Single();
            var model = compilation.GetSemanticModel(tree);
            for (var match = System.Text.RegularExpressions.Regex.Match(source, " => x"); match.Success; match = match.NextMatch())
            {
                var x = tree.GetRoot().FindToken(match.Index + 4).Parent;
                var discarded = model.GetEnclosingSymbol(match.Index);
                var disc = model.GetSymbolInfo(x);
            }
        }
 
        [Fact, WorkItem(1504, "https://github.com/dotnet/roslyn/issues/1504")]
        public void ContainingSymbol04()
        {
            var source =
@"using System;
class C
{
    static bool G<T>(Func<T> f) => true;
    static void F()
    {
        Exception x1 = null, x2 = null;
        if (G(() => x1));
        {
            G(() => x2);
        }
    }
}";
 
            var compilation = CreateCompilationWithMscorlib40AndDocumentationComments(source);
            var model = compilation.GetSemanticModel(compilation.SyntaxTrees.Single());
            var discarded1 = model.GetEnclosingSymbol(source.LastIndexOf(" => x"));
            var discarded2 = model.GetEnclosingSymbol(source.IndexOf(" => x"));
        }
 
        [WorkItem(976, "https://github.com/dotnet/roslyn/issues/976")]
        [Fact]
        public void ConstantValueOfInterpolatedString()
        {
            var source = @"
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($""Hello, world!"");
        Console.WriteLine($""{DateTime.Now.ToString()}.{args[0]}"");
    }
}";
 
            var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var actual = tree.GetRoot().DescendantNodes().OfType<InterpolatedStringExpressionSyntax>().ToArray();
            Assert.True(model.GetConstantValue(actual[0]).HasValue);
            Assert.Equal("Hello, world!", model.GetConstantValue(actual[0]).Value);
            Assert.False(model.GetConstantValue(actual[1]).HasValue);
        }
 
        [Fact]
        public void ConstantValueOfInterpolatedStringComplex()
        {
            var source = @"
class Program
{
    static void Main(string[] args)
    {
        const string S1 = $""Number 3"";
        Console.WriteLine($""{""Level 5""} {S1}"");
        Console.WriteLine($""Level {5} {S1}"");
    }
 
    void M(string S1 = $""Testing"", Namae n = null)
    {
        if (n is Namae { X : $""ConstantInterpolatedString""}){
            switch(S1){
                case $""Level 5"":
                    break;
                case $""Radio Noise"":
                    goto case $""Level 5"";
            }
        }
        S1 = S0;
    }
}";
 
            var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var actual = tree.GetRoot().DescendantNodes().OfType<InterpolatedStringExpressionSyntax>().ToArray();
            Assert.Equal(@"$""Number 3""", actual[0].ToString());
            Assert.Equal("Number 3", model.GetConstantValue(actual[0]).Value);
 
            Assert.Equal(@"$""{""Level 5""} {S1}""", actual[1].ToString());
            Assert.Equal("Level 5 Number 3", model.GetConstantValue(actual[1]).Value);
 
            Assert.False(model.GetConstantValue(actual[2]).HasValue);
 
            Assert.Equal(@"$""Testing""", actual[3].ToString());
            Assert.Equal("Testing", model.GetConstantValue(actual[3]).Value);
 
            Assert.Equal(@"$""ConstantInterpolatedString""", actual[4].ToString());
            Assert.Equal("ConstantInterpolatedString", model.GetConstantValue(actual[4]).Value);
 
            Assert.Equal(@"$""Level 5""", actual[5].ToString());
            Assert.Equal("Level 5", model.GetConstantValue(actual[5]).Value);
 
            Assert.Equal(@"$""Radio Noise""", actual[6].ToString());
            Assert.Equal("Radio Noise", model.GetConstantValue(actual[6]).Value);
 
            Assert.Equal(@"$""Level 5""", actual[7].ToString());
            Assert.Equal("Level 5", model.GetConstantValue(actual[7]).Value);
        }
 
        [WorkItem(976, "https://github.com/dotnet/roslyn/issues/976")]
        [Fact]
        public void ConstantValueOfRawInterpolatedString()
        {
            var source = @"
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($""""""Hello, world!"""""");
        Console.WriteLine($""""""{DateTime.Now.ToString()}.{args[0]}"""""");
    }
}";
 
            var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var actual = tree.GetRoot().DescendantNodes().OfType<InterpolatedStringExpressionSyntax>().ToArray();
            Assert.True(model.GetConstantValue(actual[0]).HasValue);
            Assert.Equal("Hello, world!", model.GetConstantValue(actual[0]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[0]).Type.SpecialType);
            Assert.False(model.GetConstantValue(actual[1]).HasValue);
        }
 
        [WorkItem(976, "https://github.com/dotnet/roslyn/issues/976")]
        [Fact]
        public void ConstantValueOfRawInterpolatedString2()
        {
            var source = @"
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($""""""{0}.{true}"""""");
    }
}";
 
            var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var actual = tree.GetRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().ToArray();
 
            Assert.True(model.GetConstantValue(actual[0]).HasValue);
            Assert.Equal(0, model.GetConstantValue(actual[0]).Value);
            Assert.Equal(SpecialType.System_Int32, model.GetTypeInfo(actual[0]).Type.SpecialType);
 
            Assert.True(model.GetConstantValue(actual[1]).HasValue);
            Assert.Equal(true, model.GetConstantValue(actual[1]).Value);
            Assert.Equal(SpecialType.System_Boolean, model.GetTypeInfo(actual[1]).Type.SpecialType);
        }
 
        [WorkItem(976, "https://github.com/dotnet/roslyn/issues/976")]
        [Fact]
        public void ConstantValueOfRawInterpolatedString3()
        {
            var source = @"
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($""""""{null}"""""");
    }
}";
 
            var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var actual = tree.GetRoot().DescendantNodes().OfType<LiteralExpressionSyntax>().ToArray();
 
            Assert.True(model.GetConstantValue(actual[0]).HasValue);
            Assert.Null(model.GetConstantValue(actual[0]).Value);
            Assert.Null(model.GetTypeInfo(actual[0]).Type);
        }
 
        [Fact]
        public void ConstantValueOfRawInterpolatedStringComplex()
        {
            var source = @"
class Program
{
    static void Main(string[] args)
    {
        const string S1 = $""""""Number 3"""""";
        Console.WriteLine($""""""{""""""Level 5""""""} {S1}"""""");
        Console.WriteLine($""""""Level {5} {S1}"""""");
    }
 
    void M(string S1 = $""""""Testing"""""", Namae n = null)
    {
        if (n is Namae { X : $""""""ConstantInterpolatedString""""""}){
            switch(S1){
                case $""""""Level 5"""""":
                    break;
                case $""""""Radio Noise"""""":
                    goto case $""""""Level 5"""""";
            }
        }
        S1 = S0;
    }
}";
 
            var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
 
            var actual = tree.GetRoot().DescendantNodes().OfType<InterpolatedStringExpressionSyntax>().ToArray();
            Assert.Equal(@"$""""""Number 3""""""", actual[0].ToString());
            Assert.Equal("Number 3", model.GetConstantValue(actual[0]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[0]).Type.SpecialType);
 
            Assert.Equal(@"$""""""{""""""Level 5""""""} {S1}""""""", actual[1].ToString());
            Assert.Equal("Level 5 Number 3", model.GetConstantValue(actual[1]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[1]).Type.SpecialType);
 
            Assert.False(model.GetConstantValue(actual[2]).HasValue);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[2]).Type.SpecialType);
 
            Assert.Equal(@"$""""""Testing""""""", actual[3].ToString());
            Assert.Equal("Testing", model.GetConstantValue(actual[3]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[3]).Type.SpecialType);
 
            Assert.Equal(@"$""""""ConstantInterpolatedString""""""", actual[4].ToString());
            Assert.Equal("ConstantInterpolatedString", model.GetConstantValue(actual[4]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[4]).Type.SpecialType);
 
            Assert.Equal(@"$""""""Level 5""""""", actual[5].ToString());
            Assert.Equal("Level 5", model.GetConstantValue(actual[5]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[5]).Type.SpecialType);
 
            Assert.Equal(@"$""""""Radio Noise""""""", actual[6].ToString());
            Assert.Equal("Radio Noise", model.GetConstantValue(actual[6]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[6]).Type.SpecialType);
 
            Assert.Equal(@"$""""""Level 5""""""", actual[7].ToString());
            Assert.Equal("Level 5", model.GetConstantValue(actual[7]).Value);
            Assert.Equal(SpecialType.System_String, model.GetTypeInfo(actual[7]).Type.SpecialType);
        }
 
        [WorkItem(814, "https://github.com/dotnet/roslyn/issues/814")]
        [Fact]
        public void TypeOfDynamic()
        {
            var source = @"
using System;
using System.Dynamic;
    class Program
    {
        static void Main(string[] args)
        {
            dynamic a = 5;
        }   
     }
";
            var comp = CreateCompilation(source, options: TestOptions.ReleaseExe);
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
            var typeSyntax = SyntaxFactory.ParseTypeName("dynamic");
            int spanStart = source.IndexOf("dynamic a = 5;");
            var dynamicType = model.GetSpeculativeTypeInfo(spanStart, typeSyntax, SpeculativeBindingOption.BindAsTypeOrNamespace);
            Assert.Equal(TypeKind.Dynamic, dynamicType.Type.TypeKind);
        }
 
        [Fact]
        public void IsAccessible()
        {
            var source =
@"using System;
class A
{
    public int X;
    protected int Y;
    private protected int Z;
}
class B : A
{
    void Goo()
    {
        // in B.Goo
    }
    // in B class level
    int field;
}
class C
{
    void Goo()
    {
        // in C.Goo
    }
}
namespace N
{
    // in N
}";
            var compilation = CreateCompilation(source, parseOptions: TestOptions.Regular7_2);
            compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).Verify();
 
            var tree = compilation.SyntaxTrees[0];
            var text = tree.GetText().ToString();
            var semanticModel = compilation.GetSemanticModel(tree);
            int positionInB = text.IndexOf("in B class level");
            int positionInBGoo = text.IndexOf("in B.Goo");
            int positionInCGoo = text.IndexOf("in C.Goo");
            int positionInN = text.IndexOf("in N");
 
            var globalNs = compilation.GlobalNamespace;
            var classA = (NamedTypeSymbol)globalNs.GetMembers("A").Single();
            var fieldX = (IFieldSymbol)classA.GetMembers("X").Single().ISymbol;
            var fieldY = (IFieldSymbol)classA.GetMembers("Y").Single().ISymbol;
            var fieldZ = (IFieldSymbol)classA.GetMembers("Z").Single().ISymbol;
 
            Assert.True(semanticModel.IsAccessible(positionInN, fieldX));
            Assert.False(semanticModel.IsAccessible(positionInN, fieldY));
            Assert.False(semanticModel.IsAccessible(positionInN, fieldZ));
            Assert.True(semanticModel.IsAccessible(positionInB, fieldX));
            Assert.True(semanticModel.IsAccessible(positionInB, fieldY));
            Assert.True(semanticModel.IsAccessible(positionInB, fieldZ));
            Assert.True(semanticModel.IsAccessible(positionInBGoo, fieldX));
            Assert.True(semanticModel.IsAccessible(positionInBGoo, fieldY));
            Assert.True(semanticModel.IsAccessible(positionInBGoo, fieldZ));
            Assert.True(semanticModel.IsAccessible(positionInCGoo, fieldX));
            Assert.False(semanticModel.IsAccessible(positionInCGoo, fieldY));
            Assert.False(semanticModel.IsAccessible(positionInCGoo, fieldZ));
        }
 
        [Fact, WorkItem(40201, "https://github.com/dotnet/roslyn/issues/40201")]
        public void SpeculativeModelConflictingNameUnary_DeclarationPattern()
        {
            var source = @"
using System.Threading;
 
class C
{
    void Test()
    {
        var ct = CancellationToken.None;
        if (!(this.Helper(CancellationToken.None) is string nonDiscard))
        {
        }
    }
 
    object Helper(CancellationToken ct) { return null; }
}
";
 
            var replacementSource = @"
        if (!(this.Helper(CancellationToken.None) is var nonDiscard))
        {
        }";
 
            var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7_3);
 
            var syntaxTree = comp.SyntaxTrees[0];
            var root = syntaxTree.GetRoot();
            var model = comp.GetSemanticModel(syntaxTree);
 
            var ifStatement = root.DescendantNodes().OfType<IfStatementSyntax>().Single();
            var replacementIfStatement = (IfStatementSyntax)SyntaxFactory.ParseStatement(replacementSource);
 
            Assert.True(model.TryGetSpeculativeSemanticModel(ifStatement.SpanStart, replacementIfStatement, out var specModel));
 
            var originalTypeInfo = model.GetTypeInfo(ifStatement.Condition);
            Assert.Equal(SpecialType.System_Boolean, originalTypeInfo.Type.SpecialType);
 
            var speculativeTypeInfo = specModel.GetTypeInfo(replacementIfStatement.Condition);
            Assert.Equal(SpecialType.System_Boolean, speculativeTypeInfo.Type.SpecialType);
        }
 
        [Fact, WorkItem(52013, "https://github.com/dotnet/roslyn/issues/52013")]
        public void NameOf_ArgumentDoesNotExist()
        {
            var source = @"
using System.Diagnostics;
 
public partial class C
{
    [Conditional(nameof(DEBUG))]
    void M() { }
 
";
            var comp = CreateCompilation(source);
            var method = (IMethodSymbol)comp.GetTypeByMetadataName("C").GetMembers("M").Single().GetPublicSymbol();
            var attribute = method.GetAttributes().Single();
            Assert.Equal("DEBUG", attribute.ConstructorArguments[0].Value);
 
            var tree = comp.SyntaxTrees.Single();
            var root = tree.GetRoot();
 
            var model = comp.GetSemanticModel(tree);
            Assert.Equal("DEBUG", model.GetConstantValue(root.DescendantNodes().OfType<InvocationExpressionSyntax>().Single()));
        }
 
        [Theory, CombinatorialData, WorkItem(54437, "https://github.com/dotnet/roslyn/issues/54437")]
        public void TestVarTuple(NullableContextOptions nullableContextOption)
        {
            var source = """
                var (a1, b1) = ("", 0);
                """;
            var options = WithNullable(TestOptions.DebugExe, nullableContextOption);
            var comp = CreateCompilation(source, options: options, parseOptions: TestOptions.Regular9);
            comp.VerifyDiagnostics();
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
            var root = tree.GetCompilationUnitRoot();
 
            var declarationExpression = root.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single();
            var varNode = declarationExpression.Type;
 
            var varTypeInfo = model.GetTypeInfo(varNode);
            var declarationExpressionTypeInfo = model.GetTypeInfo(declarationExpression);
            assertTypeInfo(varTypeInfo);
            Assert.Equal(varTypeInfo, declarationExpressionTypeInfo);
 
            var varSymbolInfo = model.GetSymbolInfo(varNode);
            assertSymbolInfo(varSymbolInfo);
 
            var declarationExpressionSymbolInfo = model.GetSymbolInfo(declarationExpression);
            Assert.Equal(SymbolInfo.None, declarationExpressionSymbolInfo);
 
            static void assertTypeInfo(TypeInfo typeInfo)
            {
                Assert.Equal(CodeAnalysis.NullableAnnotation.None, typeInfo.Nullability.Annotation);
                Assert.Equal(CodeAnalysis.NullableAnnotation.None, typeInfo.ConvertedNullability.Annotation);
 
                Assert.NotNull(typeInfo.Type);
                Assert.NotNull(typeInfo.ConvertedType);
                Assert.Equal(typeInfo.Type, typeInfo.ConvertedType);
 
                var type = (INamedTypeSymbol)typeInfo.Type;
                Assert.True(type.IsTupleType);
                Assert.Equal(2, type.Arity);
                Assert.Equal(2, type.TupleElements.Length);
                Assert.Equal(SpecialType.System_String, type.TupleElements[0].Type.SpecialType);
                Assert.Equal(SpecialType.System_Int32, type.TupleElements[1].Type.SpecialType);
            }
 
            static void assertSymbolInfo(SymbolInfo symbolInfo)
            {
                Assert.False(symbolInfo.IsEmpty);
                Assert.Empty(symbolInfo.CandidateSymbols);
                Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
                Assert.Equal("(System.String a1, System.Int32 b1)", symbolInfo.Symbol.ToTestDisplayString());
            }
        }
 
        [Theory, CombinatorialData, WorkItem(54437, "https://github.com/dotnet/roslyn/issues/54437")]
        public void TestVarTupleWithVarTypeInScope(NullableContextOptions nullableContextOption)
        {
            var source = """
                var (a1, b1) = ("", 0);
                class @var { }
                """;
            var options = WithNullable(TestOptions.DebugExe, nullableContextOption);
            var comp = CreateCompilation(source, options: options, parseOptions: TestOptions.Regular9);
            comp.VerifyDiagnostics(
                // (1,5): error CS8136: Deconstruction 'var (...)' form disallows a specific type for 'var'.
                // var (a1, b1) = ("", 0);
                Diagnostic(ErrorCode.ERR_DeconstructionVarFormDisallowsSpecificType, "(a1, b1)").WithLocation(1, 5),
                // (1,17): error CS0029: Cannot implicitly convert type 'string' to 'var'
                // var (a1, b1) = ("", 0);
                Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""""").WithArguments("string", "var").WithLocation(1, 17),
                // (1,21): error CS0029: Cannot implicitly convert type 'int' to 'var'
                // var (a1, b1) = ("", 0);
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "0").WithArguments("int", "var").WithLocation(1, 21));
 
            var tree = comp.SyntaxTrees.Single();
            var model = comp.GetSemanticModel(tree);
            var root = tree.GetCompilationUnitRoot();
 
            var declarationExpression = root.DescendantNodes().OfType<DeclarationExpressionSyntax>().Single();
            var varNode = declarationExpression.Type;
 
            var varTypeInfo = model.GetTypeInfo(varNode);
            var declarationExpressionTypeInfo = model.GetTypeInfo(declarationExpression);
            assertTypeInfoForVar(varTypeInfo);
            assertTypeInfoForDeclarationExpression(declarationExpressionTypeInfo);
 
            var varSymbolInfo = model.GetSymbolInfo(varNode);
            assertSymbolInfo(varSymbolInfo);
 
            var declarationExpressionSymbolInfo = model.GetSymbolInfo(declarationExpression);
            Assert.Equal(SymbolInfo.None, declarationExpressionSymbolInfo);
 
            static void assertTypeInfoForVar(TypeInfo typeInfo)
            {
                Assert.Equal(CodeAnalysis.NullableAnnotation.None, typeInfo.Nullability.Annotation);
                Assert.Equal(CodeAnalysis.NullableAnnotation.None, typeInfo.ConvertedNullability.Annotation);
 
                Assert.NotNull(typeInfo.Type);
                Assert.NotNull(typeInfo.ConvertedType);
                Assert.Equal(typeInfo.Type, typeInfo.ConvertedType);
 
                var type = (INamedTypeSymbol)typeInfo.Type;
                Assert.Equal("var", type.ToTestDisplayString());
                Assert.Equal(TypeKind.Class, type.TypeKind);
            }
 
            static void assertTypeInfoForDeclarationExpression(TypeInfo typeInfo)
            {
                Assert.Equal(CodeAnalysis.NullableAnnotation.None, typeInfo.Nullability.Annotation);
                Assert.Equal(CodeAnalysis.NullableAnnotation.None, typeInfo.ConvertedNullability.Annotation);
 
                Assert.NotNull(typeInfo.Type);
                Assert.NotNull(typeInfo.ConvertedType);
                Assert.Equal(typeInfo.Type, typeInfo.ConvertedType);
 
                var type = (INamedTypeSymbol)typeInfo.Type;
                Assert.True(type.IsTupleType);
                Assert.Equal(2, type.Arity);
                Assert.Equal(2, type.TupleElements.Length);
                Assert.Equal(TypeKind.Class, type.TupleElements[0].Type.TypeKind);
                Assert.Equal(TypeKind.Class, type.TupleElements[1].Type.TypeKind);
            }
 
            static void assertSymbolInfo(SymbolInfo symbolInfo)
            {
                Assert.False(symbolInfo.IsEmpty);
                Assert.Empty(symbolInfo.CandidateSymbols);
                Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
                Assert.Equal("var", symbolInfo.Symbol.ToTestDisplayString());
            }
        }
 
        [Fact]
        public void EqualsOnAliasSymbolWithNullContainingAssembly_NotEquals()
        {
            var text = @"
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute("".NETCoreApp, Version = v6.0"", FrameworkDisplayName = """")]
";
            var alias1 = getGlobalAlias(CreateCompilation(text));
            var alias2 = getGlobalAlias(CreateCompilation(text));
 
            Assert.Equal("<global namespace>", alias1.ContainingSymbol.ToTestDisplayString());
            Assert.Null(alias1.ContainingAssembly);
            Assert.False(alias1.Equals(alias2));
 
            static IAliasSymbol getGlobalAlias(CSharpCompilation compilation)
            {
                var tree = compilation.SyntaxTrees.Single();
                var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(ident => ident.Identifier.Text == "global").Single();
                return compilation.GetSemanticModel(tree).GetAliasInfo(node);
            }
        }
 
        [Fact]
        public void EqualsOnAliasSymbolWithNullContainingAssembly_Equals()
        {
            var text = @"
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute("".NETCoreApp, Version = v6.0"", FrameworkDisplayName = """")]
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute("".NETCoreApp, Version = v6.0"", FrameworkDisplayName = """")]
";
            var compilation = CreateCompilation(text);
            var tree = compilation.SyntaxTrees.Single();
            var nodes = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(ident => ident.Identifier.Text == "global").ToArray();
            var model = compilation.GetSemanticModel(tree);
            var alias1 = model.GetAliasInfo(nodes[0]);
            var alias2 = model.GetAliasInfo(nodes[1]);
 
            Assert.Equal("<global namespace>", alias1.ContainingSymbol.ToTestDisplayString());
            Assert.Null(alias1.ContainingAssembly);
            Assert.True(alias1.Equals(alias2));
        }
 
        [Fact]
        public void OutVarInRankSpecifier_LocalDeclaration()
        {
            var text = @"
int[M(out var x)] i = null;
";
            var compilation = CreateCompilation(text);
 
            var tree = compilation.SyntaxTrees.Single();
            var identifier = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Single(i => i.Identifier.Text == "M");
            var model = compilation.GetSemanticModel(tree);
            Assert.Null(model.GetAliasInfo(identifier));
        }
 
        [Theory]
        [InlineData("out")]
        [InlineData("ref")]
        public void OutVarInRankSpecifier_LocalFunctionParameter(string modifier)
        {
            var text = $$"""
void M({{modifier}} Type[M2(out object y)])
{
}
""";
            var compilation = CreateCompilation(text);
            var tree = compilation.SyntaxTrees.Single();
            var identifier = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Single(i => i.Identifier.Text == "M2");
            var model = compilation.GetSemanticModel(tree);
            Assert.Null(model.GetAliasInfo(identifier));
        }
 
        [Fact]
        public void OutVarInRankSpecifier_LocalFunctionReturn()
        {
            var text = @"
Type[M2(out object y)] M()
{
}
";
            var compilation = CreateCompilation(text);
            var tree = compilation.SyntaxTrees.Single();
            var identifier = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Single(i => i.Identifier.Text == "M2");
            var model = compilation.GetSemanticModel(tree);
            Assert.Null(model.GetAliasInfo(identifier));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/66806")]
        public void OutVarInRankSpecifier()
        {
            var text = @"
bool TryGet(out [NotNullWhen( object x, out object y, out object z)
{
    return true;
}
";
            var compilation = CreateCompilation(text);
            var tree = compilation.SyntaxTrees.Single();
            var identifier = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Single(i => i.Identifier.Text == "NotNullWhen");
            var model = compilation.GetSemanticModel(tree);
            Assert.Null(model.GetAliasInfo(identifier));
        }
 
        [Fact]
        public void OutVarInRankSpecifier_TypeConstraint()
        {
            var text = @"
void M<T>() where T : int[M2(out var x)]
{
}
";
            var compilation = CreateCompilation(text);
 
            var tree = compilation.SyntaxTrees.Single();
            var identifier = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Single(i => i.Identifier.Text == "M2");
            var model = compilation.GetSemanticModel(tree);
            Assert.Null(model.GetAliasInfo(identifier));
        }
 
        [Fact]
        public void OutVarInRankSpecifier_MethodParameter()
        {
            var text = @"
class C
{
    void M(out Type[M2(out object y)])
    {
    }
}
";
            var compilation = CreateCompilation(text);
 
            var tree = compilation.SyntaxTrees.Single();
            var identifier = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Single(i => i.Identifier.Text == "M2");
            var model = compilation.GetSemanticModel(tree);
            Assert.Null(model.GetAliasInfo(identifier));
        }
 
        [Fact]
        public void OutVarInRankSpecifier_PrimaryConstructorParameter()
        {
            var text = @"
class C(out Type[M2(out object y)])
{
}
";
            var compilation = CreateCompilation(text);
 
            var tree = compilation.SyntaxTrees.Single();
            var identifier = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Single(i => i.Identifier.Text == "M2");
            var model = compilation.GetSemanticModel(tree);
            Assert.Null(model.GetAliasInfo(identifier));
        }
 
        #region "regression helper"
        private void Regression(string text)
        {
            var tree = Parse(text);
            var compilation = CreateCompilation(tree);
            var model = compilation.GetSemanticModel(tree);
            var exprSynList = new List<ExpressionSyntax>();
            GetExpressionSyntax(tree.GetCompilationUnitRoot(), exprSynList);
 
            // Console.WriteLine("Roslyn Symbol Info: ");
            foreach (var exprSyn in exprSynList)
            {
                var expr = exprSyn.ToString();
                // Console.WriteLine("Expression: " + expr);
                var type = model.GetTypeInfo(exprSyn).Type;
                // Console.WriteLine("Type: " + type);
                // Console.WriteLine();
            }
        }
        private static void GetExpressionSyntax(SyntaxNode node, List<ExpressionSyntax> exprSynList)
        {
            if (node is ExpressionSyntax)
                exprSynList.Add(node as ExpressionSyntax);
 
            foreach (var child in node.ChildNodesAndTokens())
                if (child.IsNode)
                    GetExpressionSyntax(child.AsNode(), exprSynList);
        }
        #endregion
 
    }
}