Skip to content

Commit

Permalink
Enable specifying top-level binder options via an internal compilatio…
Browse files Browse the repository at this point in the history
…n option
  • Loading branch information
tmat committed Jan 21, 2016
1 parent 95c847d commit 43a72d9
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 25 deletions.
17 changes: 10 additions & 7 deletions src/Compilers/CSharp/Portable/Binder/Binder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ internal partial class Binder

internal readonly BinderFlags Flags;

/// <summary>
/// Used to create a root binder.
/// </summary>
internal Binder(CSharpCompilation compilation)
{
Debug.Assert(compilation != null);
this.Flags = compilation.Options.TopLevelBinderFlags;
this.Compilation = compilation;
}

internal Binder(Binder next)
{
Debug.Assert(next != null);
Expand All @@ -29,13 +39,6 @@ internal Binder(Binder next)
this.Compilation = next.Compilation;
}

internal Binder(CSharpCompilation compilation)
{
Debug.Assert(compilation != null);
this.Flags = BinderFlags.None;
this.Compilation = compilation;
}

protected Binder(Binder next, BinderFlags flags)
{
Debug.Assert(next != null);
Expand Down
32 changes: 27 additions & 5 deletions src/Compilers/CSharp/Portable/CSharpCompilationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Roslyn.Utilities;
using System.Diagnostics;
using System.ComponentModel;

namespace Microsoft.CodeAnalysis.CSharp
{
Expand All @@ -27,6 +28,12 @@ public sealed class CSharpCompilationOptions : CompilationOptions, IEquatable<CS
/// </summary>
public ImmutableArray<string> Usings { get; private set; }

/// <summary>
/// Flags applied to the top-level binder created for each syntax tree in the compilation
/// as well as for the binder of global imports.
/// </summary>
internal BinderFlags TopLevelBinderFlags { get; private set; }

// Defaults correspond to the compiler's defaults or indicate that the user did not specify when that is significant.
// That's significant when one option depends on another's setting. SubsystemVersion depends on Platform and Target.
public CSharpCompilationOptions(
Expand Down Expand Up @@ -68,7 +75,8 @@ public CSharpCompilationOptions(
assemblyIdentityComparer: assemblyIdentityComparer,
strongNameProvider: strongNameProvider,
metadataImportOptions: MetadataImportOptions.Public,
publicSign: publicSign)
publicSign: publicSign,
topLevelBinderFlags: BinderFlags.None)
{
}

Expand Down Expand Up @@ -101,7 +109,8 @@ internal CSharpCompilationOptions(
AssemblyIdentityComparer assemblyIdentityComparer,
StrongNameProvider strongNameProvider,
MetadataImportOptions metadataImportOptions,
bool publicSign)
bool publicSign,
BinderFlags topLevelBinderFlags)
: base(outputKind, reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName,
cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign, publicSign, optimizationLevel, checkOverflow,
platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions.ToImmutableDictionaryOrEmpty(),
Expand All @@ -111,6 +120,7 @@ internal CSharpCompilationOptions(
{
this.Usings = usings.AsImmutableOrEmpty();
this.AllowUnsafe = allowUnsafe;
this.TopLevelBinderFlags = topLevelBinderFlags;
}

private CSharpCompilationOptions(CSharpCompilationOptions other) : this(
Expand Down Expand Up @@ -141,10 +151,16 @@ private CSharpCompilationOptions(CSharpCompilationOptions other) : this(
strongNameProvider: other.StrongNameProvider,
metadataImportOptions: other.MetadataImportOptions,
reportSuppressedDiagnostics: other.ReportSuppressedDiagnostics,
publicSign: other.PublicSign)
publicSign: other.PublicSign,
topLevelBinderFlags: other.TopLevelBinderFlags)
{
}

internal CSharpCompilationOptions WithTopLevelBinderFlags(BinderFlags flags)
{
return (flags == TopLevelBinderFlags) ? this : new CSharpCompilationOptions(this) { TopLevelBinderFlags = flags };
}

internal override ImmutableArray<string> GetImports() => Usings;

public new CSharpCompilationOptions WithOutputKind(OutputKind kind)
Expand Down Expand Up @@ -585,6 +601,7 @@ public bool Equals(CSharpCompilationOptions other)
}

return this.AllowUnsafe == other.AllowUnsafe &&
this.TopLevelBinderFlags == other.TopLevelBinderFlags &&
(this.Usings == null ? other.Usings == null : this.Usings.SequenceEqual(other.Usings, StringComparer.Ordinal));
}

Expand All @@ -597,7 +614,8 @@ public override int GetHashCode()
{
return Hash.Combine(base.GetHashCodeHelper(),
Hash.Combine(this.AllowUnsafe,
Hash.Combine(Hash.CombineValues(this.Usings, StringComparer.Ordinal), 0)));
Hash.Combine(Hash.CombineValues(this.Usings, StringComparer.Ordinal),
Hash.Combine(TopLevelBinderFlags.GetHashCode(), 0))));
}

internal override Diagnostic FilterDiagnostic(Diagnostic diagnostic)
Expand All @@ -606,6 +624,7 @@ internal override Diagnostic FilterDiagnostic(Diagnostic diagnostic)
}

// 1.1 BACKCOMPAT OVERLOAD -- DO NOT TOUCH
[EditorBrowsable(EditorBrowsableState.Never)]
public CSharpCompilationOptions(
OutputKind outputKind,
string moduleName,
Expand Down Expand Up @@ -645,6 +664,7 @@ public CSharpCompilationOptions(


// 1.0 BACKCOMPAT OVERLOAD -- DO NOT TOUCH
[EditorBrowsable(EditorBrowsableState.Never)]
public CSharpCompilationOptions(
OutputKind outputKind,
string moduleName,
Expand Down Expand Up @@ -685,6 +705,7 @@ public CSharpCompilationOptions(
// Bad constructor -- DO NOT USE
// Violates the rules for optional parameter overloads detailed at
// https://github.com/dotnet/roslyn/blob/e8fdb391703dcb5712ff6a5b83d768d784cba4cf/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md
[EditorBrowsable(EditorBrowsableState.Never)]
public CSharpCompilationOptions(
OutputKind outputKind,
bool reportSuppressedDiagnostics,
Expand Down Expand Up @@ -723,7 +744,8 @@ public CSharpCompilationOptions(
assemblyIdentityComparer: assemblyIdentityComparer,
strongNameProvider: strongNameProvider,
metadataImportOptions: MetadataImportOptions.Public,
publicSign: false)
publicSign: false,
topLevelBinderFlags: BinderFlags.None)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public void Invariants()
TestProperty((old, value) => old.WithMetadataReferenceResolver(value), opt => opt.MetadataReferenceResolver, new TestMetadataReferenceResolver());
TestProperty((old, value) => old.WithAssemblyIdentityComparer(value), opt => opt.AssemblyIdentityComparer, new DesktopAssemblyIdentityComparer(new AssemblyPortabilityPolicy()));
TestProperty((old, value) => old.WithStrongNameProvider(value), opt => opt.StrongNameProvider, new DesktopStrongNameProvider());

TestProperty((old, value) => old.WithTopLevelBinderFlags(value), opt => opt.TopLevelBinderFlags, BinderFlags.IgnoreCorLibraryDuplicatedTypes);
TestProperty((old, value) => old.WithMetadataImportOptions(value), opt => opt.MetadataImportOptions, MetadataImportOptions.Internal);
}

[Fact]
Expand Down Expand Up @@ -319,7 +322,8 @@ public void TestFieldsForEqualsAndGetHashCode()
ReflectionAssert.AssertPublicAndInternalFieldsAndProperties(
typeof(CSharpCompilationOptions),
"AllowUnsafe",
"Usings");
"Usings",
"TopLevelBinderFlags");
}

[Fact]
Expand Down Expand Up @@ -356,12 +360,14 @@ private static CSharpCompilationOptions CreateCSharpCompilationOptions()
StrongNameProvider strongNameProvider = new DesktopStrongNameProvider();
MetadataImportOptions metadataImportOptions = 0;
bool reportSuppressedDiagnostics = false;
var topLevelBinderFlags = BinderFlags.None;
var publicSign = false;

return new CSharpCompilationOptions(OutputKind.ConsoleApplication, reportSuppressedDiagnostics, moduleName, mainTypeName, scriptClassName, usings,
optimizationLevel, checkOverflow, allowUnsafe, cryptoKeyContainer, cryptoKeyFile, cryptoPublicKey, delaySign,
platform, generalDiagnosticOption, warningLevel, specificDiagnosticOptions,
concurrentBuild, deterministic, extendedCustomDebugInformation, debugPlusMode, xmlReferenceResolver, sourceReferenceResolver, metadataReferenceResolver,
assemblyIdentityComparer, strongNameProvider, metadataImportOptions,
publicSign: false);
assemblyIdentityComparer, strongNameProvider, metadataImportOptions, publicSign, topLevelBinderFlags);
}

private sealed class MetadataReferenceResolverWithEquality : MetadataReferenceResolver
Expand Down
47 changes: 47 additions & 0 deletions src/Compilers/CSharp/Test/Symbol/Symbols/TypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,53 @@ static void Main()
Diagnostic(ErrorCode.ERR_SameFullNameAggAgg, "N.C").WithArguments("A, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "N.C", "B, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"));
}

[WorkItem(320, "https://github.com/dotnet/cli/issues/320")]
[Fact]
public void DuplicateCoreFxPublicTypes()
{
var sysConsoleSrc = @"
[assembly: System.Reflection.AssemblyVersion(""4.0.0.0"")]
namespace System
{
public static class Console
{
public static void Foo() {}
}
}
";
var sysConsoleRef = CreateCompilation(
sysConsoleSrc,
new[] { SystemRuntimePP7Ref },
TestOptions.ReleaseDll.WithCryptoPublicKey(TestResources.TestKeys.PublicKey_b03f5f7f11d50a3a),
assemblyName: "System.Console").EmitToImageReference();

var mainSrc = @"
System.Console.Foo();
Foo();
";

var main1 = CreateCompilation(
new[] { Parse(mainSrc, options: TestOptions.Script) },
new[] { MscorlibRef_v46, sysConsoleRef },
TestOptions.ReleaseDll.WithUsings("System.Console"));

main1.VerifyDiagnostics(
// error CS0433: The type 'Console' exists in both 'System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Diagnostic(ErrorCode.ERR_SameFullNameAggAgg).WithArguments("System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Console", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"),
// (1,9): error CS0433: The type 'Console' exists in both 'System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
Diagnostic(ErrorCode.ERR_SameFullNameAggAgg, "System.Console").WithArguments("System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Console", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"),
// (2,9): error CS0103: The name 'Foo' does not exist in the current context
Diagnostic(ErrorCode.ERR_NameNotInContext, "Foo").WithArguments("Foo"));

var main2 = CreateCompilation(
new[] { Parse(mainSrc, options: TestOptions.Script) },
new[] { MscorlibRef_v46, sysConsoleRef, SystemRuntimeFacadeRef },
TestOptions.ReleaseDll.WithUsings("System.Console").WithTopLevelBinderFlags(BinderFlags.IgnoreCorLibraryDuplicatedTypes));

main2.VerifyDiagnostics();
}

[Fact]
public void SimpleGeneric()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,14 +641,7 @@ private static Binder CreateBinderChain(
@namespace = @namespace.ContainingNamespace;
}

var binder = (new BuckStopsHereBinder(compilation)).WithAdditionalFlags(
BinderFlags.SuppressObsoleteChecks |
BinderFlags.IgnoreAccessibility |
BinderFlags.UnsafeRegion |
BinderFlags.UncheckedRegion |
BinderFlags.AllowManagedAddressOf |
BinderFlags.AllowAwaitInUnsafeContext |
BinderFlags.IgnoreCorLibraryDuplicatedTypes);
Binder binder = new BuckStopsHereBinder(compilation);
var hasImports = !importRecordGroups.IsDefaultOrEmpty;
var numImportStringGroups = hasImports ? importRecordGroups.Length : 0;
var currentStringGroup = numImportStringGroups - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ private static CSharpCompilation ToCompilation(this ImmutableArray<MetadataRefer
platform: Platform.AnyCpu, // Platform should match PEModule.Machine, in this case I386.
optimizationLevel: OptimizationLevel.Release,
assemblyIdentityComparer: IdentityComparer).
WithMetadataImportOptions(MetadataImportOptions.All);
WithMetadataImportOptions(MetadataImportOptions.All).
WithTopLevelBinderFlags(
BinderFlags.SuppressObsoleteChecks |
BinderFlags.IgnoreAccessibility |
BinderFlags.UnsafeRegion |
BinderFlags.UncheckedRegion |
BinderFlags.AllowManagedAddressOf |
BinderFlags.AllowAwaitInUnsafeContext |
BinderFlags.IgnoreCorLibraryDuplicatedTypes);
}
}
2 changes: 1 addition & 1 deletion src/Scripting/CSharp/CSharpScriptCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public override Compilation CreateSubmission(Script script)
sourceReferenceResolver: script.Options.SourceResolver,
metadataReferenceResolver: script.Options.MetadataResolver,
assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default
),
).WithTopLevelBinderFlags(BinderFlags.IgnoreCorLibraryDuplicatedTypes),
previousSubmission,
script.ReturnType,
script.GlobalsType
Expand Down

0 comments on commit 43a72d9

Please sign in to comment.