提交 610022af 编写于 作者: A Andrew Casey
上级 154ab390
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
......
......@@ -112,6 +112,7 @@
<Compile Include="Semantics\OverloadResolutionTests.cs" />
<Compile Include="Semantics\PropertyAccessTests.cs" />
<Compile Include="Semantics\QueryTests.cs" />
<Compile Include="Semantics\InteractiveUsingTests.cs" />
<Compile Include="Semantics\ScriptSemanticsTests.cs" />
<Compile Include="Semantics\SemanticAnalyzerTests.cs" />
<Compile Include="Semantics\SemanticErrorTests.cs" />
......@@ -143,4 +144,4 @@
<Import Project="..\..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using Microsoft.CodeAnalysis.Test.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class InteractiveUsingTests : CSharpTestBase
{
[Fact]
public void Using()
{
var sub = CreateSubmission("using System;typeof(String)");
sub.VerifyDiagnostics();
Assert.Equal(SpecialType.System_String, GetSpeculativeType(sub, "String").SpecialType);
}
[Fact]
public void Alias()
{
var sub = CreateSubmission("using I = System.Int32;");
sub.VerifyDiagnostics();
Assert.Equal(SpecialType.System_Int32, GetSpeculativeType(sub, "I").SpecialType);
}
[Fact]
public void UsingStatic()
{
var sub = CreateSubmission("using static System.Environment;");
sub.VerifyDiagnostics();
Assert.Equal(SymbolKind.Property, GetSpeculativeSymbol(sub, "NewLine").Kind);
}
[WorkItem(5450, "https://github.com/dotnet/roslyn/issues/5450")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/5450")]
public void GlobalUsings()
{
var sub1 = CreateSubmission(
"Combine(Environment.NewLine, Environment.NewLine)",
options: TestOptions.DebugDll.WithUsings("System", "System.IO.Path"));
sub1.VerifyDiagnostics();
// No global usings specified - expect to reuse previous.
var sub2 = CreateSubmission(
"Combine(Environment.NewLine, Environment.NewLine)",
previous: sub1);
sub2.VerifyDiagnostics();
// Global usings specified - expect to append to previous.
var sub3 = CreateSubmission(
"new StringBuilder().Append(Combine(Environment.NewLine, Environment.NewLine))",
previous: sub2,
options: TestOptions.DebugDll.WithUsings("System.Text"));
sub3.VerifyDiagnostics();
}
[WorkItem(4811, "https://github.com/dotnet/roslyn/issues/4811")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/4811")]
public void AliasCurrentSubmission()
{
const string source = @"
using T = Type;
class Type { }
";
var sub = CreateSubmission(source);
sub.VerifyDiagnostics();
var typeSymbol = sub.ScriptClass.GetMember("Type");
var tree = sub.SyntaxTrees.Single();
var model = sub.GetSemanticModel(tree);
var syntax = tree.GetRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Single();
var aliasSymbol = model.GetDeclaredSymbol(syntax);
Assert.Equal(SymbolKind.Alias, aliasSymbol.Kind);
Assert.Equal(typeSymbol, ((AliasSymbol)aliasSymbol).Target);
Assert.Equal(typeSymbol, model.GetSymbolInfo(syntax.Name).Symbol);
Assert.Equal(typeSymbol, GetSpeculativeType(sub, "Type"));
}
[WorkItem(4811, "https://github.com/dotnet/roslyn/issues/4811")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/4811")]
public void AliasPreviousSubmission()
{
var sub1 = CreateSubmission("class A { }");
var sub2 = CreateSubmission("class B : A { }", previous: sub1);
var sub3 = CreateSubmission("class C : B { }", previous: sub2);
CreateSubmission("using A1 = A;", previous: sub3).VerifyDiagnostics();
CreateSubmission("using B1 = B;", previous: sub3).VerifyDiagnostics();
var sub4 = CreateSubmission("using C1 = C;", previous: sub3);
sub4.VerifyDiagnostics();
var typeSymbol = sub3.ScriptClass.GetMember("C");
var tree = sub4.SyntaxTrees.Single();
var model = sub4.GetSemanticModel(tree);
var syntax = tree.GetRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Single();
var aliasSymbol = model.GetDeclaredSymbol(syntax);
Assert.Equal(SymbolKind.Alias, aliasSymbol.Kind);
Assert.Equal(typeSymbol, ((AliasSymbol)aliasSymbol).Target);
Assert.Equal(typeSymbol, model.GetSymbolInfo(syntax.Name).Symbol);
Assert.Equal(typeSymbol, GetSpeculativeType(sub4, "C1"));
}
[Fact]
public void AliasUnqualified()
{
const string source = @"
using I = Int32;
using System;
";
var expectedDiagnostics = new[]
{
// (2,11): error CS0246: The type or namespace name 'Int32' could not be found (are you missing a using directive or an assembly reference?)
// using I = Int32;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int32").WithArguments("Int32").WithLocation(2, 11)
};
CreateCompilationWithMscorlib(source).GetDiagnostics().Where(d => d.Severity > DiagnosticSeverity.Hidden).Verify(expectedDiagnostics);
CreateSubmission(source).GetDiagnostics().Verify(expectedDiagnostics);
}
[Fact]
public void AliasUnqualified_GlobalUsing()
{
const string source = @"
using I = Int32;
";
var expectedDiagnostics = new[]
{
// (2,11): error CS0246: The type or namespace name 'Int32' could not be found (are you missing a using directive or an assembly reference?)
// using I = Int32;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int32").WithArguments("Int32").WithLocation(2, 11)
};
var options = TestOptions.DebugDll.WithUsings("System");
CreateCompilationWithMscorlib(source, options: options).GetDiagnostics().Where(d => d.Severity > DiagnosticSeverity.Hidden).Verify(expectedDiagnostics);
CreateSubmission(source, options: options).GetDiagnostics().Verify(expectedDiagnostics);
}
[Fact]
public void AliasOtherAlias()
{
const string source = @"
using I = System.Int32;
using J = I;
";
var expectedDiagnostics = new[]
{
// (3,11): error CS0246: The type or namespace name 'I' could not be found (are you missing a using directive or an assembly reference?)
// using J = I;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I").WithArguments("I").WithLocation(3, 11)
};
CreateCompilationWithMscorlib(source).GetDiagnostics().Where(d => d.Severity > DiagnosticSeverity.Hidden).Verify(expectedDiagnostics);
CreateSubmission(source).GetDiagnostics().Verify(expectedDiagnostics);
}
[Fact]
public void AliasHiding()
{
var sub1 = CreateSubmission("using A = System.Int32;");
Assert.Equal(SpecialType.System_Int32, GetSpeculativeType(sub1, "A").SpecialType);
var sub2 = CreateSubmission("using A = System.Int16;", previous: sub1);
Assert.Equal(SpecialType.System_Int16, GetSpeculativeType(sub2, "A").SpecialType);
var sub3 = CreateSubmission("class A { }", previous: sub2);
Assert.Equal(sub3.ScriptClass, GetSpeculativeType(sub3, "A").ContainingType);
var sub4 = CreateSubmission("using A = System.Int64;", previous: sub3);
Assert.Equal(SpecialType.System_Int64, GetSpeculativeType(sub4, "A").SpecialType);
}
[WorkItem(4811, "https://github.com/dotnet/roslyn/issues/4811")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/4811")]
public void UsingStaticCurrentSubmission()
{
const string source = @"
using static Type;
class Type
{
public static readonly int Field = 1;
}
";
var sub = CreateSubmission(source);
sub.VerifyDiagnostics();
Assert.Equal(sub.ScriptClass.GetMember("Type"), GetSpeculativeSymbol(sub, "Field").ContainingType);
}
[WorkItem(4811, "https://github.com/dotnet/roslyn/issues/4811")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/4811")]
public void UsingStaticPreviousSubmission()
{
var sub1 = CreateSubmission("class A { public static int AA; }");
var sub2 = CreateSubmission("class B { public static int BB; }", previous: sub1);
var sub3 = CreateSubmission("class C { public static int CC; }", previous: sub2);
CreateSubmission("using static A;", previous: sub3).VerifyDiagnostics();
CreateSubmission("using static B;", previous: sub3).VerifyDiagnostics();
var sub4 = CreateSubmission("using static C;", previous: sub3);
sub4.VerifyDiagnostics();
var typeSymbol = sub3.ScriptClass.GetMember("C");
Assert.Equal(typeSymbol, GetSpeculativeSymbol(sub4, "CC").ContainingType);
}
[Fact]
public void UsingStaticUnqualified()
{
const string source = @"
using static Path;
using System.IO;
";
var expectedDiagnostics = new[]
{
// (2,14): error CS0246: The type or namespace name 'Path' could not be found (are you missing a using directive or an assembly reference?)
// using static Path;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Path").WithArguments("Path").WithLocation(2, 14)
};
CreateCompilationWithMscorlib(source).GetDiagnostics().Where(d => d.Severity > DiagnosticSeverity.Hidden).Verify(expectedDiagnostics);
CreateSubmission(source).GetDiagnostics().Verify(expectedDiagnostics);
}
[Fact]
public void UsingStaticUnqualified_GlobalUsing()
{
const string source = @"
using static Path;
";
var expectedDiagnostics = new[]
{
// (2,14): error CS0246: The type or namespace name 'Path' could not be found (are you missing a using directive or an assembly reference?)
// using static Path;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Path").WithArguments("Path").WithLocation(2, 14)
};
var options = TestOptions.DebugDll.WithUsings("System");
CreateCompilationWithMscorlib(source, options: options).GetDiagnostics().Where(d => d.Severity > DiagnosticSeverity.Hidden).Verify(expectedDiagnostics);
CreateSubmission(source, options: options).GetDiagnostics().Verify(expectedDiagnostics);
}
[Fact]
public void DuplicateUsing_SameSubmission()
{
CreateSubmission("using System; using System;").VerifyDiagnostics(
// (1,21): warning CS0105: The using directive for 'System' appeared previously in this namespace
// using System; using System;
Diagnostic(ErrorCode.WRN_DuplicateUsing, "System").WithArguments("System").WithLocation(1, 21));
}
[Fact]
public void DuplicateUsing_DifferentSubmissions()
{
CreateSubmission("using System;", previous: CreateSubmission("using System;")).VerifyDiagnostics();
}
[Fact]
public void UsingsRebound()
{
const string libSourceTemplate = @"
namespace A
{{
public class A{0} {{ }}
}}
namespace B
{{
public class B{0} {{ }}
}}
";
var lib1 = CreateCompilationWithMscorlib(string.Format(libSourceTemplate, 1), assemblyName: "Lib1").EmitToImageReference();
var lib2 = CreateCompilationWithMscorlib(string.Format(libSourceTemplate, 2), assemblyName: "Lib2").EmitToImageReference();
var options = TestOptions.DebugDll.WithUsings("B");
var sub1 = CreateSubmission("using A;", new[] { lib1 }, options);
sub1.VerifyDiagnostics();
var sub2 = CreateSubmission("typeof(A1) == typeof(A2) && typeof(B1) == typeof(B2)", new[] { lib1, lib2 }, options: options, previous: sub1);
sub2.VerifyDiagnostics();
}
[WorkItem(5423, "https://github.com/dotnet/roslyn/issues/5423")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/5423")]
void UsingsFromLoadedScript()
{
const string scriptSource = @"
using static System.IO.Path;
using System.IO;
using F = System.IO.File;
class C { }
";
const string submissionSource = @"
#load ""a.csx""
System.Type t;
GetTempPath(); // using static not exposed
t = typeof(File); // using not exposed
t = typeof(F); // using alias not exposed
t = typeof(C); // declaration exposed
";
var resolver = TestSourceReferenceResolver.Create(new Dictionary<string, string>
{
{ "a.csx", scriptSource }
});
var compilation = CreateSubmission(
submissionSource,
options: TestOptions.DebugDll.WithSourceReferenceResolver(resolver));
compilation.VerifyDiagnostics(
// (6,1): error CS0103: The name 'GetTempPath' does not exist in the current context
// GetTempPath(); // using static not exposed
Diagnostic(ErrorCode.ERR_NameNotInContext, "GetTempPath").WithArguments("GetTempPath").WithLocation(6, 1),
// (7,12): error CS0246: The type or namespace name 'File' could not be found (are you missing a using directive or an assembly reference?)
// t = typeof(File); // using not exposed
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "File").WithArguments("File").WithLocation(7, 12),
// (8,12): error CS0246: The type or namespace name 'F' could not be found (are you missing a using directive or an assembly reference?)
// t = typeof(F); // using alias not exposed
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "F").WithArguments("F").WithLocation(8, 12));
}
[WorkItem(5423, "https://github.com/dotnet/roslyn/issues/5423")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/5423")]
void UsingsToLoadedScript()
{
const string scriptSource = @"
System.Type t;
GetTempPath(); // using static not exposed
t = typeof(File); // using not exposed
t = typeof(F); // using alias not exposed
t = typeof(C); // declaration exposed
";
const string submissionSource = @"
#load ""a.csx""
using static System.IO.Path;
using System.IO;
using F = System.IO.File;
class C { }
";
var resolver = TestSourceReferenceResolver.Create(new Dictionary<string, string>
{
{ "a.csx", scriptSource }
});
var compilation = CreateSubmission(
submissionSource,
options: TestOptions.DebugDll.WithSourceReferenceResolver(resolver));
compilation.VerifyDiagnostics(
// a.csx(4,1): error CS0103: The name 'GetTempPath' does not exist in the current context
// GetTempPath(); // using static not exposed
Diagnostic(ErrorCode.ERR_NameNotInContext, "GetTempPath").WithArguments("GetTempPath").WithLocation(4, 1),
// a.csx(5,12): error CS0246: The type or namespace name 'File' could not be found (are you missing a using directive or an assembly reference?)
// t = typeof(File); // using not exposed
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "File").WithArguments("File").WithLocation(5, 12),
// a.csx(6,12): error CS0246: The type or namespace name 'F' could not be found (are you missing a using directive or an assembly reference?)
// t = typeof(F); // using alias not exposed
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "F").WithArguments("F").WithLocation(6, 12));
}
[Fact]
void GlobalUsingsToLoadedScript()
{
const string scriptSource = @"
System.Type t;
GetTempPath(); // global using static exposed
t = typeof(File); // global using exposed
";
const string submissionSource = @"
#load ""a.csx""
";
var resolver = TestSourceReferenceResolver.Create(new Dictionary<string, string>
{
{ "a.csx", scriptSource }
});
var compilation = CreateSubmission(
submissionSource,
options: TestOptions.DebugDll.WithSourceReferenceResolver(resolver).WithUsings("System.IO", "System.IO.Path"));
compilation.VerifyDiagnostics();
}
private static Symbol GetSpeculativeSymbol(CSharpCompilation comp, string name)
{
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
return (Symbol)model.GetSpeculativeSymbolInfo(
tree.Length,
SyntaxFactory.IdentifierName(name),
SpeculativeBindingOption.BindAsExpression).Symbol;
}
private static TypeSymbol GetSpeculativeType(CSharpCompilation comp, string name)
{
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
return (TypeSymbol)model.GetSpeculativeTypeInfo(
tree.Length,
SyntaxFactory.IdentifierName(name),
SpeculativeBindingOption.BindAsTypeOrNamespace).Type;
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Xunit;
using Roslyn.Test.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
......@@ -91,56 +86,12 @@ private static SourceReferenceResolver CreateResolver(params KeyValuePair<string
{
sources.Add(script.Key, script.Value);
}
return new TestSourceReferenceResolver(sources);
return TestSourceReferenceResolver.Create(sources);
}
private static KeyValuePair<string, string> Script(string path, string source)
{
return new KeyValuePair<string, string>(path, source);
}
private class TestSourceReferenceResolver : SourceReferenceResolver
{
private readonly IDictionary<string, string> _sources;
public static TestSourceReferenceResolver Default { get; } = new TestSourceReferenceResolver();
public TestSourceReferenceResolver(IDictionary<string, string> sources = null)
{
_sources = sources;
}
public override string NormalizePath(string path, string baseFilePath)
{
return path;
}
public override string ResolveReference(string path, string baseFilePath)
{
return ((_sources != null) && _sources.ContainsKey(path)) ? path : null;
}
public override Stream OpenRead(string resolvedPath)
{
if (_sources != null)
{
return new MemoryStream(Encoding.UTF8.GetBytes(_sources[resolvedPath]));
}
else
{
throw new IOException();
}
}
public override bool Equals(object other)
{
return this.Equals(other);
}
public override int GetHashCode()
{
return this.GetHashCode();
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using Microsoft.CodeAnalysis;
namespace Roslyn.Test.Utilities
{
public sealed class TestSourceReferenceResolver : SourceReferenceResolver
{
public static readonly SourceReferenceResolver Default = new TestSourceReferenceResolver(sources: null);
public static SourceReferenceResolver Create(Dictionary<string, string> sources = null)
{
return (sources == null || sources.Count == 0) ? Default : new TestSourceReferenceResolver(sources);
}
private readonly Dictionary<string, string> _sources;
private TestSourceReferenceResolver(Dictionary<string, string> sources)
{
_sources = sources;
}
public override string NormalizePath(string path, string baseFilePath) => path;
public override string ResolveReference(string path, string baseFilePath) =>
_sources?.ContainsKey(path) == true ? path : null;
public override Stream OpenRead(string resolvedPath)
{
if (_sources != null && resolvedPath != null)
{
return new MemoryStream(Encoding.UTF8.GetBytes(_sources[resolvedPath]));
}
else
{
throw new IOException();
}
}
public override bool Equals(object other) => ReferenceEquals(this, other);
public override int GetHashCode() => RuntimeHelpers.GetHashCode(this);
}
}
......@@ -117,6 +117,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>TestResource.resx</DependentUpon>
</Compile>
<Compile Include="TestSourceReferenceResolver.cs" />
<Compile Include="TraceListener.cs" />
<Compile Include="Traits.cs" />
<Compile Include="Win32Res.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册