提交 57d43f27 编写于 作者: A Andrew Casey

Stop exposing imports to #loaded files

Fixes #5423
上级 fc47157b
......@@ -270,6 +270,11 @@ internal virtual ImportChain ImportChain
}
}
internal virtual Imports GetImports(ConsList<Symbol> basesBeingResolved)
{
return _next.GetImports(basesBeingResolved);
}
/// <summary>
/// The type containing the binding context
/// </summary>
......
......@@ -801,6 +801,12 @@ internal InContainerBinder VisitCompilationUnit(CompilationUnitSyntax compilatio
// + script class members and using aliases
//
bool isSubmissionTree = compilation.IsSubmissionSyntaxTree(compilationUnit.SyntaxTree);
if (!isSubmissionTree)
{
result = result.WithAdditionalFlags(BinderFlags.InLoadedSyntaxTree);
}
// This is declared here so it can be captured. It's initialized below.
InContainerBinder scriptClassBinder = null;
......@@ -814,7 +820,8 @@ internal InContainerBinder VisitCompilationUnit(CompilationUnitSyntax compilatio
// NB: This binder has a full Imports object, but only the non-alias imports are
// ever consumed. Aliases are actually checked in scriptClassBinder (below).
result = compilation.PreviousSubmission == null
// Note: #loaded trees don't consume previous submission imports.
result = compilation.PreviousSubmission == null || !isSubmissionTree
? new InContainerBinder(result, basesBeingResolved => scriptClassBinder.GetImports(basesBeingResolved))
: new InContainerBinder(result, basesBeingResolved =>
compilation.GetPreviousSubmissionImports().Concat(scriptClassBinder.GetImports(basesBeingResolved)));
......
......@@ -93,6 +93,11 @@ internal enum BinderFlags : uint
/// </summary>
InScriptUsing = 1 << 27,
/// <summary>
/// In a file that has been included in the compilation via #load.
/// </summary>
InLoadedSyntaxTree = 1 << 28,
// Groups
AllClearedAtExecutableCodeBoundary = InLockBody | InCatchBlock | InCatchFilter | InFinallyBlock | InTryBlockOfTryCatch | InNestedFinallyBlock,
......
......@@ -246,7 +246,24 @@ private void LookupMembersInSubmissions(LookupResult result, TypeSymbol submissi
var isCurrentSubmission = submission == Compilation;
var considerUsings = !(isCurrentSubmission && this.Flags.Includes(BinderFlags.InScriptUsing));
var submissionImports = considerUsings ? submission.GetSubmissionImports() : Imports.Empty;
Imports submissionImports;
if (!considerUsings)
{
submissionImports = Imports.Empty;
}
else if (!this.Flags.Includes(BinderFlags.InLoadedSyntaxTree))
{
submissionImports = submission.GetSubmissionImports();
}
else if (isCurrentSubmission)
{
submissionImports = this.GetImports(basesBeingResolved);
}
else
{
submissionImports = Imports.Empty;
}
// If a viable using alias and a matching member are both defined in the submission an error is reported elsewhere.
// Ignore the member in such case.
......
......@@ -35,6 +35,11 @@ internal override ImportChain ImportChain
}
}
internal override Imports GetImports(ConsList<Symbol> basesBeingResolved)
{
return Imports.Empty;
}
protected override SourceLocalSymbol LookupLocal(SyntaxToken nameToken)
{
return null;
......
......@@ -66,12 +66,7 @@ internal NamespaceOrTypeSymbol Container
}
}
internal Imports GetImports()
{
return GetImports(basesBeingResolved: null);
}
internal Imports GetImports(ConsList<Symbol> basesBeingResolved)
internal override Imports GetImports(ConsList<Symbol> basesBeingResolved)
{
Debug.Assert(_lazyImports != null || _computeImports != null, "Have neither imports nor a way to compute them.");
......@@ -92,7 +87,7 @@ internal override ImportChain ImportChain
ImportChain importChain = this.Next.ImportChain;
if ((object)_container == null || _container.Kind == SymbolKind.Namespace)
{
importChain = new ImportChain(GetImports(), importChain);
importChain = new ImportChain(GetImports(basesBeingResolved: null), importChain);
}
Interlocked.CompareExchange(ref _lazyImportChain, importChain, null);
......@@ -146,7 +141,7 @@ internal override bool SupportsExtensionMethods
{
if (searchUsingsNotNamespace)
{
this.GetImports().LookupExtensionMethodsInUsings(methods, name, arity, options, originalBinder);
this.GetImports(basesBeingResolved: null).LookupExtensionMethodsInUsings(methods, name, arity, options, originalBinder);
}
else if (_container?.Kind == SymbolKind.Namespace)
{
......
......@@ -1200,6 +1200,13 @@ private ImplicitNamedTypeSymbol BindScriptClass()
return namespaceOrType as ImplicitNamedTypeSymbol;
}
internal bool IsSubmissionSyntaxTree(SyntaxTree tree)
{
Debug.Assert(tree != null);
Debug.Assert(!this.IsSubmission || _syntaxAndDeclarations.ExternalSyntaxTrees.Length <= 1);
return this.IsSubmission && tree == _syntaxAndDeclarations.ExternalSyntaxTrees.SingleOrDefault();
}
/// <summary>
/// Global imports (including those from previous submissions, if there are any).
/// </summary>
......@@ -1223,7 +1230,7 @@ internal Imports GetSubmissionImports()
}
var binder = GetBinderFactory(tree).GetImportsBinder((CSharpSyntaxNode)tree.GetRoot());
return binder.GetImports();
return binder.GetImports(basesBeingResolved: null);
}
/// <summary>
......@@ -1691,7 +1698,7 @@ internal Binder GetBinder(CSharpSyntaxNode syntax)
/// </summary>
internal Imports GetImports(SingleNamespaceDeclaration declaration)
{
return GetBinderFactory(declaration.SyntaxReference.SyntaxTree).GetImportsBinder((CSharpSyntaxNode)declaration.SyntaxReference.GetSyntax()).GetImports();
return GetBinderFactory(declaration.SyntaxReference.SyntaxTree).GetImportsBinder((CSharpSyntaxNode)declaration.SyntaxReference.GetSyntax()).GetImports(basesBeingResolved: null);
}
private AliasSymbol CreateGlobalNamespaceAlias()
......
......@@ -1635,7 +1635,7 @@ public override ILabelSymbol GetDeclaredSymbol(SwitchLabelSyntax declarationSynt
}
InContainerBinder binder = _binderFactory.GetImportsBinder(declarationSyntax.Parent);
var imports = binder.GetImports();
var imports = binder.GetImports(basesBeingResolved: null);
var alias = imports.UsingAliases[declarationSyntax.Alias.Name.Identifier.ValueText];
if ((object)alias.Alias == null)
......@@ -1666,7 +1666,7 @@ public override IAliasSymbol GetDeclaredSymbol(ExternAliasDirectiveSyntax declar
CheckSyntaxNode(declarationSyntax);
var binder = _binderFactory.GetImportsBinder(declarationSyntax.Parent);
var imports = binder.GetImports();
var imports = binder.GetImports(basesBeingResolved: null);
// TODO: If this becomes a bottleneck, put the extern aliases in a dictionary, as for using aliases.
foreach (var alias in imports.ExternAliases)
......
......@@ -106,7 +106,7 @@ public void ConcatCollidingExternAliases()
var tree = comp.SyntaxTrees.Single();
var binder = comp.GetBinderFactory(tree).GetImportsBinder((CSharpSyntaxNode)tree.GetRoot(), inUsing: false);
var scratchImports = binder.GetImports();
var scratchImports = binder.GetImports(basesBeingResolved: null);
var scratchExternAliases = scratchImports.ExternAliases;
Assert.Equal(2, scratchExternAliases.Length);
......@@ -145,7 +145,7 @@ private static Imports[] GetImports(params string[] sources)
var factories = trees.Select(tree => comp.GetBinderFactory(tree));
var binders = factories.Select(factory => factory.GetImportsBinder((CSharpSyntaxNode)factory.SyntaxTree.GetRoot(), inUsing: false));
var imports = binders.Select(binder => binder.GetImports());
var imports = binders.Select(binder => binder.GetImports(basesBeingResolved: null));
Assert.DoesNotContain(Imports.Empty, imports);
return imports.ToArray();
}
......
......@@ -373,17 +373,43 @@ class C { }
}
[WorkItem(5423, "https://github.com/dotnet/roslyn/issues/5423")]
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/5423")]
[Fact]
void UsingsToLoadedScript()
{
const string scriptSource = @"
using System.Collections.Generic;
using AL = System.Collections.ArrayList;
using static System.Math;
class D { }
System.Type t;
// Previous submission
GetCommandLineArgs(); // using static not exposed
t = typeof(StringBuilder); // using not exposed
t = typeof(P); // using alias not exposed
t = typeof(B); // declaration exposed
// Current submission
GetTempPath(); // using static not exposed
t = typeof(File); // using not exposed
t = typeof(F); // using alias not exposed
t = typeof(C); // declaration exposed
// Current file - all available
Sin(1);
t = typeof(List<int>);
t = typeof(AL);
t = typeof(D);
";
const string previousSubmissionSource = @"
using static System.Environment;
using System.Text;
using P = System.IO.Path;
class B { }
";
const string submissionSource = @"
......@@ -403,18 +429,33 @@ class C { }
var compilation = CreateSubmission(
submissionSource,
options: TestOptions.DebugDll.WithSourceReferenceResolver(resolver));
options: TestOptions.DebugDll.WithSourceReferenceResolver(resolver),
previous: CreateSubmission(previousSubmissionSource));
compilation.VerifyDiagnostics(
// a.csx(4,1): error CS0103: The name 'GetTempPath' does not exist in the current context
// Previous submission
// a.csx(11,1): error CS0103: The name 'GetCommandLineArgs' does not exist in the current context
// GetCommandLineArgs(); // using static not exposed
Diagnostic(ErrorCode.ERR_NameNotInContext, "GetCommandLineArgs").WithArguments("GetCommandLineArgs").WithLocation(11, 1),
// a.csx(12,12): error CS0246: The type or namespace name 'StringBuilder' could not be found (are you missing a using directive or an assembly reference?)
// t = typeof(StringBuilder); // using not exposed
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "StringBuilder").WithArguments("StringBuilder").WithLocation(12, 12),
// a.csx(13,12): error CS0246: The type or namespace name 'P' could not be found (are you missing a using directive or an assembly reference?)
// t = typeof(P); // using alias not exposed
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "P").WithArguments("P").WithLocation(13, 12),
// Current submission
// a.csx(17,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?)
Diagnostic(ErrorCode.ERR_NameNotInContext, "GetTempPath").WithArguments("GetTempPath").WithLocation(17, 1),
// a.csx(18,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?)
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "File").WithArguments("File").WithLocation(18, 12),
// a.csx(19,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));
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "F").WithArguments("F").WithLocation(19, 12));
}
[Fact]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册