提交 0b73276c 编写于 作者: C CyrusNajmabadi

Support locations being provided for Tuples and Anonymous types.

Support setting if an anonymous type's properties are mutable or not.
上级 c232013b
// 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 Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Symbols;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
...@@ -21,6 +11,16 @@ ...@@ -21,6 +11,16 @@
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Symbols;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp namespace Microsoft.CodeAnalysis.CSharp
{ {
...@@ -2703,55 +2703,21 @@ protected override IPointerTypeSymbol CommonCreatePointerTypeSymbol(ITypeSymbol ...@@ -2703,55 +2703,21 @@ protected override IPointerTypeSymbol CommonCreatePointerTypeSymbol(ITypeSymbol
return CreatePointerTypeSymbol(elementType.EnsureCSharpSymbolOrNull<ITypeSymbol, TypeSymbol>("elementType")); return CreatePointerTypeSymbol(elementType.EnsureCSharpSymbolOrNull<ITypeSymbol, TypeSymbol>("elementType"));
} }
protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(ImmutableArray<ITypeSymbol> elementTypes, ImmutableArray<string> elementNames) protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(
ImmutableArray<ITypeSymbol> elementTypes,
ImmutableArray<string> elementNames,
ImmutableArray<Location> elementLocations)
{ {
if (elementTypes.IsDefault)
{
throw new ArgumentNullException(nameof(elementTypes));
}
if (elementTypes.Length <= 1)
{
throw new ArgumentException(CodeAnalysisResources.TuplesNeedAtLeastTwoElements, nameof(elementNames));
}
elementNames = CheckTupleElementNames(elementTypes.Length, elementNames); elementNames = CheckTupleElementNames(elementTypes.Length, elementNames);
var typesBuilder = ArrayBuilder<TypeSymbol>.GetInstance(elementTypes.Length); var typesBuilder = ArrayBuilder<TypeSymbol>.GetInstance(elementTypes.Length);
for (int i = 0; i < elementTypes.Length; i++) for (int i = 0; i < elementTypes.Length; i++)
{ {
if (elementTypes[i] == null)
{
throw new ArgumentNullException($"{nameof(elementTypes)}[{i}]");
}
typesBuilder.Add(elementTypes[i].EnsureCSharpSymbolOrNull<ITypeSymbol, TypeSymbol>($"{nameof(elementTypes)}[{i}]")); typesBuilder.Add(elementTypes[i].EnsureCSharpSymbolOrNull<ITypeSymbol, TypeSymbol>($"{nameof(elementTypes)}[{i}]"));
} }
return TupleTypeSymbol.Create(null, // no location for the type declaration return TupleTypeSymbol.Create(null, // no location for the type declaration
typesBuilder.ToImmutableAndFree(), default(ImmutableArray<Location>), elementNames, this); typesBuilder.ToImmutableAndFree(), elementLocations, elementNames, this);
}
/// <summary>
/// Check that if any names are provided, and their number matches the expected cardinality.
/// Returns a normalized version of the element names (empty array if all the names are null).
/// </summary>
private static ImmutableArray<string> CheckTupleElementNames(int cardinality, ImmutableArray<string> elementNames)
{
if (!elementNames.IsDefault)
{
if (elementNames.Length != cardinality)
{
throw new ArgumentException(CodeAnalysisResources.TupleElementNameCountMismatch, nameof(elementNames));
}
if (elementNames.All(n => n == null))
{
return default(ImmutableArray<string>);
}
}
return elementNames;
} }
protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(INamedTypeSymbol underlyingType, ImmutableArray<string> elementNames) protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(INamedTypeSymbol underlyingType, ImmutableArray<string> elementNames)
...@@ -2775,15 +2741,32 @@ protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(INamedTypeSymbol ...@@ -2775,15 +2741,32 @@ protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(INamedTypeSymbol
} }
protected override INamedTypeSymbol CommonCreateAnonymousTypeSymbol( protected override INamedTypeSymbol CommonCreateAnonymousTypeSymbol(
ImmutableArray<ITypeSymbol> memberTypes, ImmutableArray<string> memberNames) ImmutableArray<ITypeSymbol> memberTypes,
ImmutableArray<string> memberNames,
ImmutableArray<Location> memberLocations,
ImmutableArray<bool> memberIsReadOnly)
{ {
for (int i = 0, n = memberTypes.Length; i < n; i++) for (int i = 0, n = memberTypes.Length; i < n; i++)
{ {
memberTypes[i].EnsureCSharpSymbolOrNull<ITypeSymbol, TypeSymbol>($"{nameof(memberTypes)}[{i}]"); memberTypes[i].EnsureCSharpSymbolOrNull<ITypeSymbol, TypeSymbol>($"{nameof(memberTypes)}[{i}]");
} }
var fields = memberTypes.ZipAsArray(memberNames, (type, name) => new AnonymousTypeField(name, Location.None, (TypeSymbol)type)); if (!memberIsReadOnly.IsDefault && memberIsReadOnly.Any(v => !v))
var descriptor = new AnonymousTypeDescriptor(fields, Location.None); {
throw new ArgumentException($"Non-ReadOnly members are not supported in C# anonymous types.");
}
var fields = ArrayBuilder<AnonymousTypeField>.GetInstance();
for (int i = 0, n = memberTypes.Length; i < n; i++)
{
var type = memberTypes[i];
var name = memberNames[i];
var location = memberLocations.IsDefault ? Location.None : memberLocations[i];
fields.Add(new AnonymousTypeField(name, location, (TypeSymbol)type));
}
var descriptor = new AnonymousTypeDescriptor(fields.ToImmutableAndFree(), Location.None);
return this.AnonymousTypeManager.ConstructAnonymousTypeSymbol(descriptor); return this.AnonymousTypeManager.ConstructAnonymousTypeSymbol(descriptor);
} }
......
// 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.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols namespace Microsoft.CodeAnalysis.CSharp.Symbols
......
...@@ -2218,6 +2218,54 @@ public void CreateAnonymousType_IncorrectLengths() ...@@ -2218,6 +2218,54 @@ public void CreateAnonymousType_IncorrectLengths()
ImmutableArray.Create("m1", "m2"))); ImmutableArray.Create("m1", "m2")));
} }
[Fact()]
public void CreateAnonymousType_IncorrectLengths_IsReadOnly()
{
var compilation = CSharpCompilation.Create("HelloWorld");
Assert.Throws<ArgumentException>(() =>
compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32),
(ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)),
ImmutableArray.Create("m1", "m2"),
ImmutableArray.Create(true)));
}
[Fact()]
public void CreateAnonymousType_IncorrectLengths_Locations()
{
var compilation = CSharpCompilation.Create("HelloWorld");
Assert.Throws<ArgumentException>(() =>
compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32),
(ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)),
ImmutableArray.Create("m1", "m2"),
memberLocations: ImmutableArray.Create(Location.None)));
}
[Fact()]
public void CreateAnonymousType_WritableProperty()
{
var compilation = CSharpCompilation.Create("HelloWorld");
Assert.Throws<ArgumentException>(() =>
compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32),
(ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)),
ImmutableArray.Create("m1", "m2"),
ImmutableArray.Create(false, false)));
}
[Fact()]
public void CreateAnonymousType_NullLocations()
{
var compilation = CSharpCompilation.Create("HelloWorld");
Assert.Throws<ArgumentException>(() =>
compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32),
(ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)),
ImmutableArray.Create("m1", "m2"),
memberLocations: ImmutableArray.Create(Location.None, null)));
}
[Fact()] [Fact()]
public void CreateAnonymousType_NullArgument1() public void CreateAnonymousType_NullArgument1()
{ {
......
...@@ -824,15 +824,75 @@ public INamedTypeSymbol GetTypeByMetadataName(string fullyQualifiedMetadataName) ...@@ -824,15 +824,75 @@ public INamedTypeSymbol GetTypeByMetadataName(string fullyQualifiedMetadataName)
protected abstract INamedTypeSymbol CommonGetTypeByMetadataName(string metadataName); protected abstract INamedTypeSymbol CommonGetTypeByMetadataName(string metadataName);
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
/// <summary> /// <summary>
/// Returns a new INamedTypeSymbol with the given element types and (optional) element names. /// Returns a new INamedTypeSymbol with the given element types and (optional) element names.
/// </summary> /// </summary>
public INamedTypeSymbol CreateTupleTypeSymbol(ImmutableArray<ITypeSymbol> elementTypes, ImmutableArray<string> elementNames = default(ImmutableArray<string>)) public INamedTypeSymbol CreateTupleTypeSymbol(
ImmutableArray<ITypeSymbol> elementTypes,
ImmutableArray<string> elementNames = default(ImmutableArray<string>),
ImmutableArray<Location> elementLocations = default(ImmutableArray<Location>))
{ {
return CommonCreateTupleTypeSymbol(elementTypes, elementNames); if (elementTypes.IsDefault)
{
throw new ArgumentNullException(nameof(elementTypes));
}
if (elementTypes.Length <= 1)
{
throw new ArgumentException(CodeAnalysisResources.TuplesNeedAtLeastTwoElements, nameof(elementNames));
}
elementNames = CheckTupleElementNames(elementTypes.Length, elementNames);
if (!elementLocations.IsDefault && elementLocations.Length != elementTypes.Length)
{
throw new ArgumentException($"{nameof(elementLocations)} must either be 'default' or have the same length as {nameof(elementTypes)}.");
}
for (int i = 0, n = elementTypes.Length; i < n; i++)
{
if (elementTypes[i] == null)
{
throw new ArgumentNullException($"{nameof(elementTypes)}[{i}]");
}
if (!elementLocations.IsDefault && elementLocations[i] == null)
{
throw new ArgumentNullException($"{nameof(elementLocations)}[{i}]");
}
}
return CommonCreateTupleTypeSymbol(elementTypes, elementNames, elementLocations);
} }
#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters
protected abstract INamedTypeSymbol CommonCreateTupleTypeSymbol(ImmutableArray<ITypeSymbol> elementTypes, ImmutableArray<string> elementNames); /// <summary>
/// Check that if any names are provided, and their number matches the expected cardinality.
/// Returns a normalized version of the element names (empty array if all the names are null).
/// </summary>
protected static ImmutableArray<string> CheckTupleElementNames(int cardinality, ImmutableArray<string> elementNames)
{
if (!elementNames.IsDefault)
{
if (elementNames.Length != cardinality)
{
throw new ArgumentException(CodeAnalysisResources.TupleElementNameCountMismatch, nameof(elementNames));
}
if (elementNames.All(n => n == null))
{
return default(ImmutableArray<string>);
}
}
return elementNames;
}
protected abstract INamedTypeSymbol CommonCreateTupleTypeSymbol(
ImmutableArray<ITypeSymbol> elementTypes,
ImmutableArray<string> elementNames,
ImmutableArray<Location> elementLocations);
/// <summary> /// <summary>
/// Returns a new INamedTypeSymbol with the given underlying type and (optional) element names. /// Returns a new INamedTypeSymbol with the given underlying type and (optional) element names.
...@@ -850,9 +910,17 @@ public INamedTypeSymbol CreateTupleTypeSymbol(INamedTypeSymbol underlyingType, I ...@@ -850,9 +910,17 @@ public INamedTypeSymbol CreateTupleTypeSymbol(INamedTypeSymbol underlyingType, I
/// <summary> /// <summary>
/// Returns a new anonymous type symbol with the given member types member names. /// Returns a new anonymous type symbol with the given member types member names.
/// Anonymous type members will be readonly by default. Writable properties are
/// supported in VB and can be created by passing in <code>false</code> in the
/// appropriate locations in <paramref name="memberIsReadOnly"/>.
///
/// Source locations can also be provided through <paramref name="memberLocations"/>
/// </summary> /// </summary>
public INamedTypeSymbol CreateAnonymousTypeSymbol( public INamedTypeSymbol CreateAnonymousTypeSymbol(
ImmutableArray<ITypeSymbol> memberTypes, ImmutableArray<string> memberNames) ImmutableArray<ITypeSymbol> memberTypes,
ImmutableArray<string> memberNames,
ImmutableArray<bool> memberIsReadOnly = default(ImmutableArray<bool>),
ImmutableArray<Location> memberLocations = default(ImmutableArray<Location>))
{ {
if (memberTypes.IsDefault) if (memberTypes.IsDefault)
{ {
...@@ -869,6 +937,16 @@ public INamedTypeSymbol CreateTupleTypeSymbol(INamedTypeSymbol underlyingType, I ...@@ -869,6 +937,16 @@ public INamedTypeSymbol CreateTupleTypeSymbol(INamedTypeSymbol underlyingType, I
throw new ArgumentException($"{nameof(memberTypes)} and {nameof(memberNames)} must have the same length."); throw new ArgumentException($"{nameof(memberTypes)} and {nameof(memberNames)} must have the same length.");
} }
if (!memberLocations.IsDefault && memberLocations.Length != memberTypes.Length)
{
throw new ArgumentException($"{nameof(memberLocations)} must either be 'default' or have the same length as {nameof(memberNames)}.");
}
if (!memberIsReadOnly.IsDefault && memberIsReadOnly.Length != memberTypes.Length)
{
throw new ArgumentException($"{nameof(memberIsReadOnly)} must either be 'default' or have the same length as {nameof(memberNames)}.");
}
for (int i = 0, n = memberTypes.Length; i < n; i++) for (int i = 0, n = memberTypes.Length; i < n; i++)
{ {
if (memberTypes[i] == null) if (memberTypes[i] == null)
...@@ -880,13 +958,21 @@ public INamedTypeSymbol CreateTupleTypeSymbol(INamedTypeSymbol underlyingType, I ...@@ -880,13 +958,21 @@ public INamedTypeSymbol CreateTupleTypeSymbol(INamedTypeSymbol underlyingType, I
{ {
throw new ArgumentNullException($"{nameof(memberNames)}[{i}]"); throw new ArgumentNullException($"{nameof(memberNames)}[{i}]");
} }
if (!memberLocations.IsDefault && memberLocations[i] == null)
{
throw new ArgumentNullException($"{nameof(memberLocations)}[{i}]");
}
} }
return CommonCreateAnonymousTypeSymbol(memberTypes, memberNames); return CommonCreateAnonymousTypeSymbol(memberTypes, memberNames, memberLocations, memberIsReadOnly);
} }
protected abstract INamedTypeSymbol CommonCreateAnonymousTypeSymbol( protected abstract INamedTypeSymbol CommonCreateAnonymousTypeSymbol(
ImmutableArray<ITypeSymbol> memberTypes, ImmutableArray<string> memberNames); ImmutableArray<ITypeSymbol> memberTypes,
ImmutableArray<string> memberNames,
ImmutableArray<Location> memberLocations,
ImmutableArray<bool> memberIsReadOnly);
#endregion #endregion
......
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
Microsoft.CodeAnalysis.CommandLineArguments.DisplayVersion.get -> bool Microsoft.CodeAnalysis.CommandLineArguments.DisplayVersion.get -> bool
Microsoft.CodeAnalysis.CommandLineArguments.EmbeddedFiles.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CommandLineSourceFile> Microsoft.CodeAnalysis.CommandLineArguments.EmbeddedFiles.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CommandLineSourceFile>
Microsoft.CodeAnalysis.CommandLineArguments.SourceLink.get -> string Microsoft.CodeAnalysis.CommandLineArguments.SourceLink.get -> string
Microsoft.CodeAnalysis.Compilation.CreateAnonymousTypeSymbol(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol> memberTypes, System.Collections.Immutable.ImmutableArray<string> memberNames) -> Microsoft.CodeAnalysis.INamedTypeSymbol Microsoft.CodeAnalysis.Compilation.CreateAnonymousTypeSymbol(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol> memberTypes, System.Collections.Immutable.ImmutableArray<string> memberNames, System.Collections.Immutable.ImmutableArray<bool> memberIsReadOnly = default(System.Collections.Immutable.ImmutableArray<bool>), System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Location> memberLocations = default(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Location>)) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(Microsoft.CodeAnalysis.INamedTypeSymbol underlyingType, System.Collections.Immutable.ImmutableArray<string> elementNames = default(System.Collections.Immutable.ImmutableArray<string>)) -> Microsoft.CodeAnalysis.INamedTypeSymbol Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(Microsoft.CodeAnalysis.INamedTypeSymbol underlyingType, System.Collections.Immutable.ImmutableArray<string> elementNames = default(System.Collections.Immutable.ImmutableArray<string>)) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol> elementTypes, System.Collections.Immutable.ImmutableArray<string> elementNames = default(System.Collections.Immutable.ImmutableArray<string>)) -> Microsoft.CodeAnalysis.INamedTypeSymbol Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol> elementTypes, System.Collections.Immutable.ImmutableArray<string> elementNames = default(System.Collections.Immutable.ImmutableArray<string>), System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Location> elementLocations = default(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Location>)) -> Microsoft.CodeAnalysis.INamedTypeSymbol
Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream = null, System.IO.Stream xmlDocumentationStream = null, System.IO.Stream win32Resources = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ResourceDescription> manifestResources = null, Microsoft.CodeAnalysis.Emit.EmitOptions options = null, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint = null, System.IO.Stream sourceLinkStream = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.EmbeddedText> embeddedTexts = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitResult Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream = null, System.IO.Stream xmlDocumentationStream = null, System.IO.Stream win32Resources = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ResourceDescription> manifestResources = null, Microsoft.CodeAnalysis.Emit.EmitOptions options = null, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint = null, System.IO.Stream sourceLinkStream = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.EmbeddedText> embeddedTexts = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitResult
Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream, System.IO.Stream xmlDocumentationStream, System.IO.Stream win32Resources, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ResourceDescription> manifestResources, Microsoft.CodeAnalysis.Emit.EmitOptions options, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.Emit.EmitResult Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream, System.IO.Stream xmlDocumentationStream, System.IO.Stream win32Resources, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ResourceDescription> manifestResources, Microsoft.CodeAnalysis.Emit.EmitOptions options, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.Emit.EmitResult
Microsoft.CodeAnalysis.CompilationOptions.WithConcurrentBuild(bool concurrent) -> Microsoft.CodeAnalysis.CompilationOptions Microsoft.CodeAnalysis.CompilationOptions.WithConcurrentBuild(bool concurrent) -> Microsoft.CodeAnalysis.CompilationOptions
......
...@@ -2577,45 +2577,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2577,45 +2577,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return CreateArrayTypeSymbol(elementType.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(elementType)), rank) Return CreateArrayTypeSymbol(elementType.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(elementType)), rank)
End Function End Function
Protected Overrides Function CommonCreateTupleTypeSymbol(elementTypes As ImmutableArray(Of ITypeSymbol), elementNames As ImmutableArray(Of String)) As INamedTypeSymbol Protected Overrides Function CommonCreateTupleTypeSymbol(elementTypes As ImmutableArray(Of ITypeSymbol),
If elementTypes.IsDefault Then elementNames As ImmutableArray(Of String),
Throw New ArgumentNullException(NameOf(elementTypes)) elementLocations As ImmutableArray(Of Location)) As INamedTypeSymbol
End If
If elementTypes.Length <= 1 Then
Throw New ArgumentException(CodeAnalysisResources.TuplesNeedAtLeastTwoElements, NameOf(elementNames))
End If
elementNames = CheckTupleElementNames(elementTypes.Length, elementNames)
Dim typesBuilder = ArrayBuilder(Of TypeSymbol).GetInstance(elementTypes.Length) Dim typesBuilder = ArrayBuilder(Of TypeSymbol).GetInstance(elementTypes.Length)
For i As Integer = 0 To elementTypes.Length - 1 For i As Integer = 0 To elementTypes.Length - 1
If elementTypes(i) Is Nothing Then
Throw New ArgumentNullException($"{NameOf(elementTypes)}[{i}]")
End If
typesBuilder.Add(elementTypes(i).EnsureVbSymbolOrNothing(Of TypeSymbol)($"{NameOf(elementTypes)}[{i}]")) typesBuilder.Add(elementTypes(i).EnsureVbSymbolOrNothing(Of TypeSymbol)($"{NameOf(elementTypes)}[{i}]"))
Next Next
'no location for the type declaration 'no location for the type declaration
Return TupleTypeSymbol.Create(locationOpt:=Nothing, elementTypes:=typesBuilder.ToImmutableAndFree(), elementLocations:=Nothing, elementNames:=elementNames, compilation:=Me) Return TupleTypeSymbol.Create(locationOpt:=Nothing,
End Function elementTypes:=typesBuilder.ToImmutableAndFree(),
elementLocations:=elementLocations,
''' <summary> elementNames:=elementNames, compilation:=Me)
''' Check that if any names are provided, their number matches the expected cardinality and they are not null.
''' </summary>
Private Shared Function CheckTupleElementNames(cardinality As Integer, elementNames As ImmutableArray(Of String)) As ImmutableArray(Of String)
If Not elementNames.IsDefault Then
If elementNames.Length <> cardinality Then
Throw New ArgumentException(CodeAnalysisResources.TupleElementNameCountMismatch, NameOf(elementNames))
End If
If elementNames.All(Function(n As String) n Is Nothing) Then
Return Nothing
End If
End If
Return elementNames
End Function End Function
Protected Overrides Function CommonCreateTupleTypeSymbol(underlyingType As INamedTypeSymbol, elementNames As ImmutableArray(Of String)) As INamedTypeSymbol Protected Overrides Function CommonCreateTupleTypeSymbol(underlyingType As INamedTypeSymbol, elementNames As ImmutableArray(Of String)) As INamedTypeSymbol
...@@ -2645,7 +2619,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2645,7 +2619,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Protected Overrides Function CommonCreateAnonymousTypeSymbol( Protected Overrides Function CommonCreateAnonymousTypeSymbol(
memberTypes As ImmutableArray(Of ITypeSymbol), memberTypes As ImmutableArray(Of ITypeSymbol),
memberNames As ImmutableArray(Of String)) As INamedTypeSymbol memberNames As ImmutableArray(Of String),
memberLocations As ImmutableArray(Of Location),
memberIsReadOnly As ImmutableArray(Of Boolean)) As INamedTypeSymbol
Dim i = 0 Dim i = 0
For Each t In memberTypes For Each t In memberTypes
...@@ -2654,11 +2630,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2654,11 +2630,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
i = i + 1 i = i + 1
Next Next
Dim fields = memberTypes.ZipAsArray( Dim fields = ArrayBuilder(Of AnonymousTypeField).GetInstance()
memberNames,
Function(type, name) New AnonymousTypeField(name, DirectCast(type, TypeSymbol), Location.None)) For i = 0 To memberTypes.Length - 1
Dim type = memberTypes(i)
Dim name = memberNames(i)
Dim loc = If(memberLocations.IsDefault, Location.None, memberLocations(i))
Dim isReadOnly = memberIsReadOnly.IsDefault OrElse memberIsReadOnly(i)
fields.Add(New AnonymousTypeField(name, DirectCast(type, TypeSymbol), loc, isReadOnly))
Next
Dim descriptor = New AnonymousTypeDescriptor(fields, Location.None, isImplicitlyDeclared:=False) Dim descriptor = New AnonymousTypeDescriptor(
fields.ToImmutableAndFree(), Location.None, isImplicitlyDeclared:=False)
Return Me.AnonymousTypeManager.ConstructAnonymousTypeSymbol(descriptor) Return Me.AnonymousTypeManager.ConstructAnonymousTypeSymbol(descriptor)
End Function End Function
......
...@@ -1303,6 +1303,45 @@ BC2014: the value '_' is invalid for option 'RootNamespace' ...@@ -1303,6 +1303,45 @@ BC2014: the value '_' is invalid for option 'RootNamespace'
End Function) End Function)
End Sub End Sub
<Fact>
Public Sub CreateAnonymousType_IncorrectLengths_IsReadOnly()
Dim compilation = VisualBasicCompilation.Create("HelloWorld")
Assert.Throws(Of ArgumentException)(
Sub()
compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create(DirectCast(compilation.GetSpecialType(SpecialType.System_Int32), ITypeSymbol),
DirectCast(compilation.GetSpecialType(SpecialType.System_Int32), ITypeSymbol)),
ImmutableArray.Create("m1", "m2"),
ImmutableArray.Create(True))
End Sub)
End Sub
<Fact>
Public sub CreateAnonymousType_IncorrectLengths_Locations()
Dim Compilation = VisualBasicCompilation.Create("HelloWorld")
Assert.Throws(Of ArgumentException)(
Sub()
Compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create(DirectCast(Compilation.GetSpecialType(SpecialType.System_Int32), ITypeSymbol),
DirectCast(Compilation.GetSpecialType(SpecialType.System_Int32), ITypeSymbol)),
ImmutableArray.Create("m1", "m2"),
memberLocations:=ImmutableArray.Create(Location.None))
End Sub)
End Sub
<Fact>
Public Sub CreateAnonymousType_WritableProperty()
Dim compilation = VisualBasicCompilation.Create("HelloWorld")
Dim type = compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create(DirectCast(compilation.GetSpecialType(SpecialType.System_Int32), ITypeSymbol),
DirectCast(compilation.GetSpecialType(SpecialType.System_Int32), ITypeSymbol)),
ImmutableArray.Create("m1", "m2"),
ImmutableArray.Create(False, False))
Assert.True(type.IsAnonymousType)
Assert.Equal(2, type.GetMembers().OfType(Of IPropertySymbol).Count())
Assert.Equal("<anonymous type: m1 As Integer, m2 As Integer>", type.ToDisplayString())
End Sub
<Fact()> <Fact()>
Public Sub CreateAnonymousType_NothingArgument() Public Sub CreateAnonymousType_NothingArgument()
Dim compilation = VisualBasicCompilation.Create("HelloWorld") Dim compilation = VisualBasicCompilation.Create("HelloWorld")
...@@ -1321,6 +1360,19 @@ BC2014: the value '_' is invalid for option 'RootNamespace' ...@@ -1321,6 +1360,19 @@ BC2014: the value '_' is invalid for option 'RootNamespace'
ImmutableArray.Create(Of ITypeSymbol)(compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create(Of ITypeSymbol)(compilation.GetSpecialType(SpecialType.System_Int32)),
ImmutableArray.Create("m1")) ImmutableArray.Create("m1"))
Assert.True(type.IsAnonymousType)
Assert.Equal(1, type.GetMembers().OfType(Of IPropertySymbol).Count())
Assert.Equal("<anonymous type: Key m1 As Integer>", type.ToDisplayString())
End Sub
<Fact()>
Public Sub CreateMutableAnonymousType1()
Dim compilation = VisualBasicCompilation.Create("HelloWorld")
Dim type = compilation.CreateAnonymousTypeSymbol(
ImmutableArray.Create(Of ITypeSymbol)(compilation.GetSpecialType(SpecialType.System_Int32)),
ImmutableArray.Create("m1"),
ImmutableArray.Create(False))
Assert.True(type.IsAnonymousType) Assert.True(type.IsAnonymousType)
Assert.Equal(1, type.GetMembers().OfType(Of IPropertySymbol).Count()) Assert.Equal(1, type.GetMembers().OfType(Of IPropertySymbol).Count())
Assert.Equal("<anonymous type: m1 As Integer>", type.ToDisplayString()) Assert.Equal("<anonymous type: m1 As Integer>", type.ToDisplayString())
...@@ -1335,7 +1387,7 @@ BC2014: the value '_' is invalid for option 'RootNamespace' ...@@ -1335,7 +1387,7 @@ BC2014: the value '_' is invalid for option 'RootNamespace'
Assert.True(type.IsAnonymousType) Assert.True(type.IsAnonymousType)
Assert.Equal(2, type.GetMembers().OfType(Of IPropertySymbol).Count()) Assert.Equal(2, type.GetMembers().OfType(Of IPropertySymbol).Count())
Assert.Equal("<anonymous type: m1 As Integer, m2 As Boolean>", type.ToDisplayString()) Assert.Equal("<anonymous type: Key m1 As Integer, Key m2 As Boolean>", type.ToDisplayString())
End Sub End Sub
<Fact()> <Fact()>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册