提交 0b0e4906 编写于 作者: G Gen Lu

Merge remote-tracking branch 'dotnet/master' into stabilization

......@@ -24,7 +24,11 @@ try
# List of binary names that should be skipped because they have a known issue that
# makes them non-deterministic.
$skipList = @()
$skipList = @(
# https://github.com/dotnet/roslyn/issues/8739
"Microsoft.VisualStudio.ProjectSystem.Managed.dll"
)
$allGood = $true
$map = @{}
......
......@@ -67,7 +67,7 @@ ImmutableArray<IArgument> IInvocationExpression.ArgumentsInSourceOrder
IArgument IHasArgumentsExpression.GetArgumentMatchingParameter(IParameterSymbol parameter)
{
return ArgumentMatchingParameter(this.Arguments, this.ArgsToParamsOpt, this.ArgumentNamesOpt, this.ArgumentRefKindsOpt, parameter.ContainingSymbol as Symbols.MethodSymbol, parameter, this.Syntax);
return ArgumentMatchingParameter(this.Arguments, this.ArgsToParamsOpt, this.ArgumentNamesOpt, this.ArgumentRefKindsOpt, parameter.ContainingSymbol, ((Symbols.MethodSymbol)parameter.ContainingSymbol).Parameters, parameter, this.Syntax);
}
protected override OperationKind ExpressionKind => OperationKind.InvocationExpression;
......@@ -199,18 +199,18 @@ private static IOperation CreateParamArray(IParameterSymbol parameter, Immutable
return null;
}
internal static IArgument ArgumentMatchingParameter(ImmutableArray<BoundExpression> arguments, ImmutableArray<int> argumentsToParameters, ImmutableArray<string> argumentNames, ImmutableArray<RefKind> argumentRefKinds, Symbols.MethodSymbol targetMethod, IParameterSymbol parameter, SyntaxNode invocationSyntax)
internal static IArgument ArgumentMatchingParameter(ImmutableArray<BoundExpression> arguments, ImmutableArray<int> argumentsToParameters, ImmutableArray<string> argumentNames, ImmutableArray<RefKind> argumentRefKinds, ISymbol targetMethod, ImmutableArray<Symbols.ParameterSymbol> parameters, IParameterSymbol parameter, SyntaxNode invocationSyntax)
{
int argumentIndex = ArgumentIndexMatchingParameter(arguments, argumentsToParameters, targetMethod, parameter);
if (argumentIndex >= 0)
{
return DeriveArgument(parameter.Ordinal, argumentIndex, arguments, argumentNames, argumentRefKinds, targetMethod.Parameters, invocationSyntax);
return DeriveArgument(parameter.Ordinal, argumentIndex, arguments, argumentNames, argumentRefKinds, parameters, invocationSyntax);
}
return null;
}
private static int ArgumentIndexMatchingParameter(ImmutableArray<BoundExpression> arguments, ImmutableArray<int> argumentsToParameters, IMethodSymbol targetMethod, IParameterSymbol parameter)
private static int ArgumentIndexMatchingParameter(ImmutableArray<BoundExpression> arguments, ImmutableArray<int> argumentsToParameters, ISymbol targetMethod, IParameterSymbol parameter)
{
if (parameter.ContainingSymbol == targetMethod)
{
......@@ -346,6 +346,34 @@ public override void Accept(OperationVisitor visitor)
}
}
internal partial class BoundIndexerAccess : IIndexedPropertyReferenceExpression
{
IPropertySymbol IPropertyReferenceExpression.Property => this.Indexer;
IOperation IMemberReferenceExpression.Instance => this.Indexer.IsStatic ? null : this.ReceiverOpt;
ISymbol IMemberReferenceExpression.Member => this.Indexer;
ImmutableArray<IArgument> IHasArgumentsExpression.ArgumentsInParameterOrder => BoundCall.DeriveArguments(this.Arguments, this.ArgumentNamesOpt, this.ArgsToParamsOpt, this.ArgumentRefKindsOpt, this.Indexer.Parameters, this.Syntax);
IArgument IHasArgumentsExpression.GetArgumentMatchingParameter(IParameterSymbol parameter)
{
return BoundCall.ArgumentMatchingParameter(this.Arguments, this.ArgsToParamsOpt, this.ArgumentNamesOpt, this.ArgumentRefKindsOpt, this.Indexer, this.Indexer.Parameters, parameter, this.Syntax);
}
protected override OperationKind ExpressionKind => OperationKind.IndexedPropertyReferenceExpression;
public override void Accept(OperationVisitor visitor)
{
visitor.VisitIndexedPropertyReferenceExpression(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitIndexedPropertyReferenceExpression(this, argument);
}
}
internal partial class BoundEventAccess : IEventReferenceExpression
{
IEventSymbol IEventReferenceExpression.Event => this.EventSymbol;
......@@ -473,7 +501,7 @@ internal partial class BoundObjectCreationExpression : IObjectCreationExpression
IArgument IHasArgumentsExpression.GetArgumentMatchingParameter(IParameterSymbol parameter)
{
return BoundCall.ArgumentMatchingParameter(this.Arguments, this.ArgsToParamsOpt, this.ArgumentNamesOpt, this.ArgumentRefKindsOpt, this.Constructor, parameter, this.Syntax);
return BoundCall.ArgumentMatchingParameter(this.Arguments, this.ArgsToParamsOpt, this.ArgumentNamesOpt, this.ArgumentRefKindsOpt, this.Constructor, this.Constructor.Parameters, parameter, this.Syntax);
}
ImmutableArray<ISymbolInitializer> IObjectCreationExpression.MemberInitializers
......@@ -761,22 +789,22 @@ public override void Accept(OperationVisitor visitor)
}
}
internal partial class BoundIsOperator : IIsExpression
internal partial class BoundIsOperator : IIsTypeExpression
{
IOperation IIsExpression.Operand => this.Operand;
IOperation IIsTypeExpression.Operand => this.Operand;
ITypeSymbol IIsExpression.IsType => this.TargetType.Type;
ITypeSymbol IIsTypeExpression.IsType => this.TargetType.Type;
protected override OperationKind ExpressionKind => OperationKind.IsExpression;
protected override OperationKind ExpressionKind => OperationKind.IsTypeExpression;
public override void Accept(OperationVisitor visitor)
{
visitor.VisitIsExpression(this);
visitor.VisitIsTypeExpression(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitIsExpression(this, argument);
return visitor.VisitIsTypeExpression(this, argument);
}
}
......@@ -1058,9 +1086,9 @@ internal partial class BoundBinaryOperator : IBinaryOperatorExpression
{
BinaryOperationKind IBinaryOperatorExpression.BinaryOperationKind => Expression.DeriveBinaryOperationKind(this.OperatorKind);
IOperation IBinaryOperatorExpression.Left => this.Left;
IOperation IBinaryOperatorExpression.LeftOperand => this.Left;
IOperation IBinaryOperatorExpression.Right => this.Right;
IOperation IBinaryOperatorExpression.RightOperand => this.Right;
bool IHasOperatorMethodExpression.UsesOperatorMethod => (this.OperatorKind & BinaryOperatorKind.TypeMask) == BinaryOperatorKind.UserDefined;
......@@ -1130,9 +1158,9 @@ public override void Accept(OperationVisitor visitor)
internal partial class BoundNullCoalescingOperator : INullCoalescingExpression
{
IOperation INullCoalescingExpression.Primary => this.LeftOperand;
IOperation INullCoalescingExpression.PrimaryOperand => this.LeftOperand;
IOperation INullCoalescingExpression.Secondary => this.RightOperand;
IOperation INullCoalescingExpression.SecondaryOperand => this.RightOperand;
protected override OperationKind ExpressionKind => OperationKind.NullCoalescingExpression;
......@@ -1236,7 +1264,9 @@ public override void Accept(OperationVisitor visitor)
internal partial class BoundConditionalAccess : IConditionalAccessExpression
{
IOperation IConditionalAccessExpression.Access => this.AccessExpression;
IOperation IConditionalAccessExpression.ConditionalValue => this.AccessExpression;
IOperation IConditionalAccessExpression.ConditionalInstance => this.Receiver;
protected override OperationKind ExpressionKind => OperationKind.ConditionalAccessExpression;
......@@ -1251,6 +1281,21 @@ public override void Accept(OperationVisitor visitor)
}
}
internal partial class BoundConditionalReceiver : IConditionalAccessInstanceExpression
{
protected override OperationKind ExpressionKind => OperationKind.ConditionalAccessInstanceExpression;
public override void Accept(OperationVisitor visitor)
{
visitor.VisitConditionalAccessInstanceExpression(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitConditionalAccessInstanceExpression(this, argument);
}
}
internal partial class BoundEqualsValue : ISymbolInitializer
{
IOperation ISymbolInitializer.Value => this.Value;
......@@ -1563,21 +1608,6 @@ public override void Accept(OperationVisitor visitor)
}
}
internal partial class BoundIndexerAccess
{
protected override OperationKind ExpressionKind => OperationKind.None;
public override void Accept(OperationVisitor visitor)
{
visitor.VisitNoneOperation(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitNoneOperation(this, argument);
}
}
internal partial class BoundSequencePointExpression
{
protected override OperationKind ExpressionKind => OperationKind.None;
......@@ -1847,22 +1877,7 @@ public override void Accept(OperationVisitor visitor)
return visitor.VisitNoneOperation(this, argument);
}
}
internal partial class BoundConditionalReceiver
{
protected override OperationKind ExpressionKind => OperationKind.None;
public override void Accept(OperationVisitor visitor)
{
visitor.VisitNoneOperation(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitNoneOperation(this, argument);
}
}
internal partial class BoundDynamicCollectionElementInitializer
{
protected override OperationKind ExpressionKind => OperationKind.None;
......@@ -2084,7 +2099,7 @@ internal static BinaryOperationKind DeriveBinaryOperationKind(UnaryOperationKind
return BinaryOperationKind.DynamicSubtract;
default:
throw ExceptionUtilities.UnexpectedValue(incrementKind);
return BinaryOperationKind.Invalid;
}
}
......@@ -2311,7 +2326,7 @@ internal static UnaryOperationKind DeriveUnaryOperationKind(UnaryOperatorKind op
break;
}
throw ExceptionUtilities.UnexpectedValue(operatorKind & UnaryOperatorKind.TypeMask);
return UnaryOperationKind.Invalid;
}
internal static BinaryOperationKind DeriveBinaryOperationKind(BinaryOperatorKind operatorKind)
......@@ -2733,7 +2748,7 @@ internal static BinaryOperationKind DeriveBinaryOperationKind(BinaryOperatorKind
break;
}
throw ExceptionUtilities.UnexpectedValue(operatorKind & BinaryOperatorKind.TypeMask);
return BinaryOperationKind.Invalid;
}
}
}
......@@ -385,8 +385,10 @@ BinaryOperationKind ISingleValueCaseClause.Equality
{
return BinaryOperationKind.EnumEquals;
}
}
return BinaryOperationKind.Invalid;
}
// Return None for `default` case.
return BinaryOperationKind.None;
}
}
......@@ -485,33 +487,24 @@ public override void Accept(OperationVisitor visitor)
}
}
internal partial class BoundUsingStatement : IUsingWithDeclarationStatement, IUsingWithExpressionStatement
internal partial class BoundUsingStatement : IUsingStatement
{
IVariableDeclarationStatement IUsingWithDeclarationStatement.Declaration => this.DeclarationsOpt;
IVariableDeclarationStatement IUsingStatement.Declaration => this.DeclarationsOpt;
IOperation IUsingWithExpressionStatement.Value => this.ExpressionOpt;
IOperation IUsingStatement.Value => this.ExpressionOpt;
IOperation IUsingStatement.Body => this.Body;
protected override OperationKind StatementKind => this.ExpressionOpt != null ? OperationKind.UsingWithExpressionStatement : OperationKind.UsingWithDeclarationStatement;
protected override OperationKind StatementKind => OperationKind.UsingStatement;
public override void Accept(OperationVisitor visitor)
{
if (this.StatementKind == OperationKind.UsingWithExpressionStatement)
{
visitor.VisitUsingWithExpressionStatement(this);
}
else
{
visitor.VisitUsingWithDeclarationStatement(this);
}
visitor.VisitUsingStatement(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return this.StatementKind == OperationKind.UsingWithExpressionStatement
? visitor.VisitUsingWithExpressionStatement(this, argument)
: visitor.VisitUsingWithDeclarationStatement(this, argument);
return visitor.VisitUsingStatement(this, argument);
}
}
......
......@@ -21,63 +21,19 @@ internal AssemblyReference(AssemblySymbol assemblySymbol)
_targetAssembly = assemblySymbol;
}
public AssemblyIdentity MetadataIdentity => _targetAssembly.Identity;
public AssemblyIdentity Identity => _targetAssembly.Identity;
public override string ToString()
{
return _targetAssembly.ToString();
}
#region Cci.IAssemblyReference
void Cci.IReference.Dispatch(Cci.MetadataVisitor visitor)
{
visitor.Visit(this);
}
string Cci.IAssemblyReference.Culture
{
get
{
return MetadataIdentity.CultureName;
}
}
bool Cci.IAssemblyReference.IsRetargetable
{
get
{
return MetadataIdentity.IsRetargetable;
}
}
AssemblyContentType Cci.IAssemblyReference.ContentType
{
get
{
return MetadataIdentity.ContentType;
}
}
ImmutableArray<byte> Cci.IAssemblyReference.PublicKeyToken
{
get { return MetadataIdentity.PublicKeyToken; }
}
Version Cci.IAssemblyReference.Version
{
get { return MetadataIdentity.Version; }
}
string Cci.IAssemblyReference.GetDisplayName()
{
return MetadataIdentity.GetDisplayName();
}
string Cci.INamedEntity.Name
{
get { return MetadataIdentity.Name; }
}
string Cci.INamedEntity.Name => Identity.Name;
Cci.IAssemblyReference Cci.IModuleReference.GetContainingAssembly(CodeAnalysis.Emit.EmitContext context)
{
......@@ -93,7 +49,5 @@ Cci.IDefinition Cci.IReference.AsDefinition(CodeAnalysis.Emit.EmitContext contex
{
return null;
}
#endregion
}
}
......@@ -161,44 +161,7 @@ protected override void AddEmbeddedResourcesFromAddedModules(ArrayBuilder<Cci.Ma
}
}
string Cci.IAssemblyReference.Culture
{
get
{
return _sourceAssembly.Identity.CultureName;
}
}
bool Cci.IAssemblyReference.IsRetargetable
{
get
{
return _sourceAssembly.Identity.IsRetargetable;
}
}
AssemblyContentType Cci.IAssemblyReference.ContentType
{
get
{
return _sourceAssembly.Identity.ContentType;
}
}
ImmutableArray<byte> Cci.IAssemblyReference.PublicKeyToken
{
get { return _sourceAssembly.Identity.PublicKeyToken; }
}
Version Cci.IAssemblyReference.Version
{
get { return _sourceAssembly.Identity.Version; }
}
string Cci.IAssemblyReference.GetDisplayName()
{
return _sourceAssembly.Identity.GetDisplayName();
}
AssemblyIdentity Cci.IAssemblyReference.Identity => _sourceAssembly.Identity;
internal override string Name
{
......
......@@ -6,6 +6,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.PortableExecutable;
using System.Threading;
using Microsoft.CodeAnalysis.CodeGen;
......@@ -136,10 +137,10 @@ protected override IEnumerable<Cci.IAssemblyReference> GetAssemblyReferencesFrom
private void ValidateReferencedAssembly(AssemblySymbol assembly, AssemblyReference asmRef, DiagnosticBag diagnostics)
{
AssemblyIdentity asmIdentity = SourceModule.ContainingAssembly.Identity;
AssemblyIdentity refIdentity = asmRef.MetadataIdentity;
AssemblyIdentity refIdentity = asmRef.Identity;
if (asmIdentity.IsStrongName && !refIdentity.IsStrongName &&
((Cci.IAssemblyReference)asmRef).ContentType != System.Reflection.AssemblyContentType.WindowsRuntime)
asmRef.Identity.ContentType != AssemblyContentType.WindowsRuntime)
{
// Dev12 reported error, we have changed it to a warning to allow referencing libraries
// built for platforms that don't support strong names.
......
......@@ -1444,5 +1444,98 @@ public void M1()
Diagnostic(NullOperationSyntaxTestAnalyzer.ParamsArrayOperationDescriptor.Id, "1").WithLocation(11, 12),
Diagnostic(NullOperationSyntaxTestAnalyzer.ParamsArrayOperationDescriptor.Id, "1").WithLocation(12, 12));
}
[WorkItem(8114, "https://github.com/dotnet/roslyn/issues/8114")]
[Fact]
public void InvalidOperatorCSharp()
{
const string source = @"
public class A
{
public bool Compare(float f)
{
return f == float.Nan; // Misspelled
}
public string Negate(string f)
{
return -f;
}
public void Increment(string f)
{
f++;
}
}
";
CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_NoSuchMember, "Nan").WithArguments("float", "Nan").WithLocation(6, 27),
Diagnostic(ErrorCode.ERR_BadUnaryOp, "-f").WithArguments("-", "string").WithLocation(11, 16),
Diagnostic(ErrorCode.ERR_BadUnaryOp, "f++").WithArguments("++", "string").WithLocation(16, 9))
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new InvalidOperatorExpressionTestAnalyzer() }, null, null, false,
Diagnostic(InvalidOperatorExpressionTestAnalyzer.InvalidBinaryDescriptor.Id, "f == float.Nan").WithLocation(6, 16),
Diagnostic(InvalidOperatorExpressionTestAnalyzer.InvalidUnaryDescriptor.Id, "-f").WithLocation(11, 16),
Diagnostic(InvalidOperatorExpressionTestAnalyzer.InvalidIncrementDescriptor.Id, "f++").WithLocation(16, 9));
}
[Fact]
public void ConditionalAccessOperationsCSharp()
{
const string source = @"
class C
{
public int Prop { get; set; }
public int Field;
public int this[int i]
{
get
{
return this.Field;
}
set
{
this.Field = value;
}
}
public C Field1 = null;
public void M0(C p)
{
var x = p?.Prop;
x = p?.Field;
x = p?[0];
p?.M0(null);
x = Field1?.Prop;
x = Field1?.Field;
x = Field1?[0];
Field1?.M0(null);
}
}
";
CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics()
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new ConditionalAccessOperationTestAnalyzer() }, null, null, false,
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?.Prop").WithLocation(24, 17),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p").WithLocation(24, 17),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?.Field").WithLocation(25, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p").WithLocation(25, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?[0]").WithLocation(26, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p").WithLocation(26, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?.M0(null)").WithLocation(27, 9),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p").WithLocation(27, 9),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?.Prop").WithLocation(29, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1").WithLocation(29, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?.Field").WithLocation(30, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1").WithLocation(30, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?[0]").WithLocation(31, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1").WithLocation(31, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?.M0(null)").WithLocation(32, 9),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1").WithLocation(32, 9));
}
}
}
\ No newline at end of file
......@@ -145,8 +145,8 @@ public sealed override void Initialize(AnalysisContext context)
if (forCondition.Kind == OperationKind.BinaryOperatorExpression)
{
IBinaryOperatorExpression condition = (IBinaryOperatorExpression)forCondition;
IOperation conditionLeft = condition.Left;
IOperation conditionRight = condition.Right;
IOperation conditionLeft = condition.LeftOperand;
IOperation conditionRight = condition.RightOperand;
if (conditionRight.ConstantValue.HasValue &&
conditionRight.Type.SpecialType == SpecialType.System_Int32 &&
......@@ -194,13 +194,13 @@ public sealed override void Initialize(AnalysisContext context)
IBinaryOperatorExpression advanceOperation = (IBinaryOperatorExpression)advanceAssignment.Value;
if (!advanceOperation.UsesOperatorMethod &&
advanceOperation.Left.Kind == OperationKind.LocalReferenceExpression &&
((ILocalReferenceExpression)advanceOperation.Left).Local == testVariable &&
advanceOperation.Right.ConstantValue.HasValue &&
advanceOperation.Right.Type.SpecialType == SpecialType.System_Int32)
advanceOperation.LeftOperand.Kind == OperationKind.LocalReferenceExpression &&
((ILocalReferenceExpression)advanceOperation.LeftOperand).Local == testVariable &&
advanceOperation.RightOperand.ConstantValue.HasValue &&
advanceOperation.RightOperand.Type.SpecialType == SpecialType.System_Int32)
{
// Advance binary operation is known to involve a reference to the local used in the test and a constant.
advanceIncrement = advanceOperation.Right;
advanceIncrement = advanceOperation.RightOperand;
advanceOperationCode = advanceOperation.BinaryOperationKind;
}
}
......@@ -1525,9 +1525,8 @@ public sealed override void Initialize(AnalysisContext context)
Diagnostic.Create(ParamsArrayOperationDescriptor,
paramsarrayArgumentOperation.Syntax.GetLocation()));
}
},
OperationKind.InvocationExpression);
OperationKind.InvocationExpression);
}
// this OperationWalker collect:
......@@ -1564,4 +1563,127 @@ public override void Visit(IOperation operation)
}
}
}
public class InvalidOperatorExpressionTestAnalyzer : DiagnosticAnalyzer
{
private const string ReliabilityCategory = "Reliability";
public static readonly DiagnosticDescriptor InvalidBinaryDescriptor = new DiagnosticDescriptor(
"InvalidBinary",
"Invalid binary expression operation with BinaryOperationKind.Invalid",
"An Invalid binary expression operation with BinaryOperationKind.Invalid is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public static readonly DiagnosticDescriptor InvalidUnaryDescriptor = new DiagnosticDescriptor(
"InvalidUnary",
"Invalid unary expression operation with UnaryOperationKind.Invalid",
"An Invalid unary expression operation with UnaryOperationKind.Invalid is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public static readonly DiagnosticDescriptor InvalidIncrementDescriptor = new DiagnosticDescriptor(
"InvalidIncrement",
"Invalid increment expression operation with ICompoundAssignmentExpression.BinaryOperationKind == BinaryOperationKind.Invalid",
"An Invalid increment expression operation with ICompoundAssignmentExpression.BinaryOperationKind == BinaryOperationKind.Invalid is found",
ReliabilityCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(InvalidBinaryDescriptor,
InvalidUnaryDescriptor,
InvalidIncrementDescriptor);
public sealed override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction(
(operationContext) =>
{
var operation = operationContext.Operation;
if (operation.Kind == OperationKind.BinaryOperatorExpression)
{
var binary = (IBinaryOperatorExpression)operation;
if (binary.IsInvalid && binary.BinaryOperationKind == BinaryOperationKind.Invalid)
{
operationContext.ReportDiagnostic(Diagnostic.Create(InvalidBinaryDescriptor, binary.Syntax.GetLocation()));
}
}
else if (operation.Kind == OperationKind.UnaryOperatorExpression)
{
var unary = (IUnaryOperatorExpression)operation;
if (unary.IsInvalid && unary.UnaryOperationKind == UnaryOperationKind.Invalid)
{
operationContext.ReportDiagnostic(Diagnostic.Create(InvalidUnaryDescriptor, unary.Syntax.GetLocation()));
}
}
else if (operation.Kind == OperationKind.IncrementExpression)
{
var inc = (IIncrementExpression)operation;
if (inc.IsInvalid && inc.BinaryOperationKind == BinaryOperationKind.Invalid)
{
operationContext.ReportDiagnostic(Diagnostic.Create(InvalidIncrementDescriptor, inc.Syntax.GetLocation()));
}
}
},
OperationKind.BinaryOperatorExpression,
OperationKind.UnaryOperatorExpression,
OperationKind.IncrementExpression);
}
}
public class ConditionalAccessOperationTestAnalyzer : DiagnosticAnalyzer
{
public static readonly DiagnosticDescriptor ConditionalAccessOperationDescriptor = new DiagnosticDescriptor(
"ConditionalAccessOperation",
"Conditional access operation found",
"Conditional access operation was found",
"Testing",
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public static readonly DiagnosticDescriptor ConditionalAccessInstanceOperationDescriptor = new DiagnosticDescriptor(
"ConditionalAccessInstanceOperation",
"Conditional access instance operation found",
"Conditional access instance operation was found",
"Testing",
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(ConditionalAccessOperationDescriptor, ConditionalAccessInstanceOperationDescriptor); }
}
public sealed override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction(
(operationContext) =>
{
IConditionalAccessExpression conditionalAccess = (IConditionalAccessExpression)operationContext.Operation;
if (conditionalAccess.ConditionalValue != null && conditionalAccess.ConditionalInstance != null)
{
operationContext.ReportDiagnostic(Diagnostic.Create(ConditionalAccessOperationDescriptor, conditionalAccess.Syntax.GetLocation()));
}
},
OperationKind.ConditionalAccessExpression);
context.RegisterOperationAction(
(operationContext) =>
{
IConditionalAccessInstanceExpression conditionalAccessInstance = (IConditionalAccessInstanceExpression)operationContext.Operation;
operationContext.ReportDiagnostic(Diagnostic.Create(ConditionalAccessInstanceOperationDescriptor, conditionalAccessInstance.Syntax.GetLocation()));
},
OperationKind.ConditionalAccessInstanceExpression);
context.RegisterOperationAction(
(operationContext) =>
{
IPlaceholderExpression placeholder = (IPlaceholderExpression)operationContext.Operation;
operationContext.ReportDiagnostic(Diagnostic.Create(ConditionalAccessInstanceOperationDescriptor, placeholder.Syntax.GetLocation()));
},
OperationKind.PlaceholderExpression);
}
}
}
\ No newline at end of file
......@@ -74,10 +74,10 @@ public static BinaryOperationKind DeriveAdditionKind(ITypeSymbol type)
if (type.TypeKind == TypeKind.Enum)
{
return Semantics.BinaryOperationKind.EnumAdd;
return BinaryOperationKind.EnumAdd;
}
return Semantics.BinaryOperationKind.None;
return BinaryOperationKind.Invalid;
}
}
......@@ -334,17 +334,17 @@ internal sealed class Binary : IBinaryOperatorExpression
public Binary(BinaryOperationKind binaryOperationKind, IOperation left, IOperation right, ITypeSymbol resultType, SyntaxNode syntax)
{
this.BinaryOperationKind = binaryOperationKind;
this.Left = left;
this.Right = right;
this.LeftOperand = left;
this.RightOperand = right;
this.Type = resultType;
this.Syntax = syntax;
}
public BinaryOperationKind BinaryOperationKind { get; }
public IOperation Left { get; }
public IOperation LeftOperand { get; }
public IOperation Right { get; }
public IOperation RightOperand { get; }
public bool UsesOperatorMethod => false;
......@@ -354,7 +354,7 @@ public Binary(BinaryOperationKind binaryOperationKind, IOperation left, IOperati
public OperationKind Kind => OperationKind.BinaryOperatorExpression;
public bool IsInvalid => Left == null || Left.IsInvalid || Right == null || Right.IsInvalid;
public bool IsInvalid => LeftOperand == null || LeftOperand.IsInvalid || RightOperand == null || RightOperand.IsInvalid;
public Optional<object> ConstantValue => default(Optional<object>);
......
......@@ -263,6 +263,13 @@ public interface IPropertyReferenceExpression : IMemberReferenceExpression
IPropertySymbol Property { get; }
}
/// <summary>
/// Represents a reference to an indexed property.
/// </summary>
public interface IIndexedPropertyReferenceExpression : IPropertyReferenceExpression, IHasArgumentsExpression
{
}
/// <summary>
/// Represents a reference to an event.
/// </summary>
......@@ -301,14 +308,33 @@ public interface IEventAssignmentExpression : IOperation
}
/// <summary>
/// Represents a conditional access expression.
/// Represents an expression that includes a ? or ?. conditional access instance expression.
/// </summary>
public interface IConditionalAccessExpression : IOperation
{
/// <summary>
/// Expression subject to conditional access.
/// Expression to be evaluated if the conditional instance is non null.
/// </summary>
IOperation ConditionalValue { get; }
/// <summary>
/// Expresson that is conditionally accessed.
/// </summary>
IOperation Access { get; }
IOperation ConditionalInstance { get; }
}
/// <summary>
/// Represents the value of a conditionally-accessed expression within an expression containing a conditional access.
/// </summary>
public interface IConditionalAccessInstanceExpression : IOperation
{
}
/// <summary>
/// Represents a general placeholder when no more specific kind of placeholder is available.
/// A placeholder is an expression whose meaning is inferred from context.
/// </summary>
public interface IPlaceholderExpression : IOperation
{
}
/// <summary>
......@@ -355,7 +381,9 @@ public enum SimpleUnaryOperationKind
Minus = 0x8,
True = 0x9,
False = 0xa,
BitwiseOrLogicalNot = 0xb
BitwiseOrLogicalNot = 0xb,
Invalid = 0xff
}
public enum UnaryOperandKind
......@@ -371,7 +399,9 @@ public enum UnaryOperandKind
Enum = 0x700,
Dynamic = 0x800,
Object = 0x900,
Pointer = 0xa00
Pointer = 0xa00,
Invalid = 0xff00
}
/// <summary>
......@@ -445,7 +475,9 @@ public enum UnaryOperationKind
ObjectPlus = UnaryOperandKind.Object | SimpleUnaryOperationKind.Plus,
ObjectMinus = UnaryOperandKind.Object | SimpleUnaryOperationKind.Minus,
ObjectNot = UnaryOperandKind.Object | SimpleUnaryOperationKind.BitwiseOrLogicalNot
ObjectNot = UnaryOperandKind.Object | SimpleUnaryOperationKind.BitwiseOrLogicalNot,
Invalid = UnaryOperandKind.Invalid | SimpleUnaryOperationKind.Invalid
}
......@@ -461,11 +493,11 @@ public interface IBinaryOperatorExpression : IHasOperatorMethodExpression
/// <summary>
/// Left operand.
/// </summary>
IOperation Left { get; }
IOperation LeftOperand { get; }
/// <summary>
/// Right operand.
/// </summary>
IOperation Right { get; }
IOperation RightOperand { get; }
}
public enum SimpleBinaryOperationKind
......@@ -499,7 +531,9 @@ public enum SimpleBinaryOperationKind
GreaterThanOrEqual = 0x16,
GreaterThan = 0x17,
Like = 0x18
Like = 0x18,
Invalid = 0xff
}
public enum BinaryOperandsKind
......@@ -520,7 +554,9 @@ public enum BinaryOperandsKind
IntegerPointer = 0xc00,
String = 0xd00,
Delegate = 0xe00,
Nullable = 0xf00
Nullable = 0xf00,
Invalid = 0xff00
}
/// <summary>
......@@ -700,7 +736,9 @@ public enum BinaryOperationKind
DynamicLessThan = BinaryOperandsKind.Dynamic | SimpleBinaryOperationKind.LessThan,
DynamicLessThanOrEqual = BinaryOperandsKind.Dynamic | SimpleBinaryOperationKind.LessThanOrEqual,
DynamicGreaterThanOrEqual = BinaryOperandsKind.Dynamic | SimpleBinaryOperationKind.GreaterThanOrEqual,
DynamicGreaterThan = BinaryOperandsKind.Dynamic | SimpleBinaryOperationKind.GreaterThan
DynamicGreaterThan = BinaryOperandsKind.Dynamic | SimpleBinaryOperationKind.GreaterThan,
Invalid = BinaryOperandsKind.Invalid | SimpleBinaryOperationKind.Invalid
}
public static class UnaryAndBinaryOperationExtensions
......@@ -869,17 +907,17 @@ public interface INullCoalescingExpression : IOperation
/// <summary>
/// Value to be unconditionally evaluated.
/// </summary>
IOperation Primary { get; }
IOperation PrimaryOperand { get; }
/// <summary>
/// Value to be evaluated if Primary evaluates to null/Nothing.
/// </summary>
IOperation Secondary { get; }
IOperation SecondaryOperand { get; }
}
/// <summary>
/// Represents an expression that tests if a value is of a specific type.
/// </summary>
public interface IIsExpression : IOperation
public interface IIsTypeExpression : IOperation
{
/// <summary>
/// Value to test.
......
......@@ -46,6 +46,8 @@ public enum OperationKind
{
None = 0x0,
// Statements
/// <summary>Indicates an <see cref="IInvalidStatement"/>.</summary>
InvalidStatement = 0x1,
/// <summary>Indicates an <see cref="IBlockStatement"/>.</summary>
......@@ -58,150 +60,163 @@ public enum OperationKind
IfStatement = 0x5,
/// <summary>Indicates an <see cref="ILoopStatement"/>.</summary>
LoopStatement = 0x6,
/// <summary>Indicates an <see cref="IReturnStatement"/>.</summary>
YieldBreakStatement = 0x9,
/// <summary>Indicates an <see cref="ILabelStatement"/>.</summary>
LabelStatement = 0xa,
LabelStatement = 0x7,
/// <summary>Indicates an <see cref="IBranchStatement"/>.</summary>
BranchStatement = 0xc,
BranchStatement = 0x8,
/// <summary>Indicates an <see cref="IEmptyStatement"/>.</summary>
EmptyStatement = 0xd,
EmptyStatement = 0x9,
/// <summary>Indicates an <see cref="IThrowStatement"/>.</summary>
ThrowStatement = 0xe,
ThrowStatement = 0xa,
/// <summary>Indicates an <see cref="IReturnStatement"/>.</summary>
ReturnStatement = 0xb,
/// <summary>Indicates an <see cref="IReturnStatement"/>.</summary>
ReturnStatement = 0xf,
YieldBreakStatement = 0xc,
/// <summary>Indicates an <see cref="ILockStatement"/>.</summary>
LockStatement = 0x10,
LockStatement = 0xd,
/// <summary>Indicates an <see cref="ITryStatement"/>.</summary>
TryStatement = 0x11,
/// <summary>Indicates an <see cref="ICatchClause"/>.</summary>
CatchClause = 0x12,
/// <summary>Indicates an <see cref="IUsingWithDeclarationStatement"/>.</summary>
UsingWithDeclarationStatement = 0x13,
/// <summary>Indicates an <see cref="IUsingWithExpressionStatement"/>.</summary>
UsingWithExpressionStatement = 0x14,
TryStatement = 0xe,
/// <summary>Indicates an <see cref="IUsingStatement"/>.</summary>
UsingStatement = 0xf,
/// <summary>Indicates an <see cref="IReturnStatement"/>.</summary>
YieldReturnStatement = 0x15,
YieldReturnStatement = 0x10,
/// <summary>Indicates an <see cref="IExpressionStatement"/>.</summary>
ExpressionStatement = 0x11,
// Statements that occur only C#.
/// <summary>Indicates an <see cref="IFixedStatement"/>.</summary>
FixedStatement = 0x16,
// LocalFunctionStatement = 0x17,
FixedStatement = 0x30,
/// <summary>Indicates an <see cref="IExpressionStatement"/>.</summary>
ExpressionStatement = 0x18,
// Statements that occur only in Visual Basic.
/// <summary>Indicates an <see cref="IStopStatement"/>.</summary>
StopStatement = 0x50,
/// <summary>Indicates an <see cref="IEndStatement"/>.</summary>
EndStatement = 0x51,
/// <summary>Indicates an <see cref="IWithStatement"/>.</summary>
WithStatement = 0x52,
// Expressions
/// <summary>Indicates an <see cref="IInvalidExpression"/>.</summary>
InvalidExpression = 0x19,
InvalidExpression = 0x100,
/// <summary>Indicates an <see cref="ILiteralExpression"/>.</summary>
LiteralExpression = 0x1a,
LiteralExpression = 0x101,
/// <summary>Indicates an <see cref="IConversionExpression"/>.</summary>
ConversionExpression = 0x1b,
ConversionExpression = 0x102,
/// <summary>Indicates an <see cref="IInvocationExpression"/>.</summary>
InvocationExpression = 0x1c,
InvocationExpression = 0x103,
/// <summary>Indicates an <see cref="IArrayElementReferenceExpression"/>.</summary>
ArrayElementReferenceExpression = 0x1d,
/// <summary>Indicates an <see cref="IPointerIndirectionReferenceExpression"/>.</summary>
PointerIndirectionReferenceExpression = 0x1e,
ArrayElementReferenceExpression = 0x104,
/// <summary>Indicates an <see cref="ILocalReferenceExpression"/>.</summary>
LocalReferenceExpression = 0x1f,
LocalReferenceExpression = 0x105,
/// <summary>Indicates an <see cref="IParameterReferenceExpression"/>.</summary>
ParameterReferenceExpression = 0x20,
ParameterReferenceExpression = 0x106,
/// <summary>Indicates an <see cref="ISyntheticLocalReferenceExpression"/>.</summary>
SyntheticLocalReferenceExpression = 0x21,
SyntheticLocalReferenceExpression = 0x107,
/// <summary>Indicates an <see cref="IFieldReferenceExpression"/>.</summary>
FieldReferenceExpression = 0x22,
FieldReferenceExpression = 0x108,
/// <summary>Indicates an <see cref="IMethodBindingExpression"/>.</summary>
MethodBindingExpression = 0x23,
MethodBindingExpression = 0x109,
/// <summary>Indicates an <see cref="IPropertyReferenceExpression"/>.</summary>
PropertyReferenceExpression = 0x24,
PropertyReferenceExpression = 0x10a,
/// <summary>Indicates an <see cref="IIndexedPropertyReferenceExpression"/>.</summary>
IndexedPropertyReferenceExpression = 0x10b,
/// <summary>Indicates an <see cref="IEventReferenceExpression"/>.</summary>
EventReferenceExpression = 0x25,
/// <summary>Indicates an <see cref="ILateBoundMemberReferenceExpression"/>.</summary>
LateBoundMemberReferenceExpression = 0x26,
EventReferenceExpression = 0x10c,
/// <summary>Indicates an <see cref="IUnaryOperatorExpression"/>.</summary>
UnaryOperatorExpression = 0x27,
UnaryOperatorExpression = 0x10d,
/// <summary>Indicates an <see cref="IBinaryOperatorExpression"/>.</summary>
BinaryOperatorExpression = 0x28,
BinaryOperatorExpression = 0x10e,
/// <summary>Indicates an <see cref="IConditionalChoiceExpression"/>.</summary>
ConditionalChoiceExpression = 0x29,
ConditionalChoiceExpression = 0x10f,
/// <summary>Indicates an <see cref="INullCoalescingExpression"/>.</summary>
NullCoalescingExpression = 0x2a,
NullCoalescingExpression = 0x110,
/// <summary>Indicates an <see cref="ILambdaExpression"/>.</summary>
LambdaExpression = 0x2b,
LambdaExpression = 0x111,
/// <summary>Indicates an <see cref="IObjectCreationExpression"/>.</summary>
ObjectCreationExpression = 0x2c,
ObjectCreationExpression = 0x112,
/// <summary>Indicates an <see cref="ITypeParameterObjectCreationExpression"/>.</summary>
TypeParameterObjectCreationExpression = 0x2d,
TypeParameterObjectCreationExpression = 0x113,
/// <summary>Indicates an <see cref="IArrayCreationExpression"/>.</summary>
ArrayCreationExpression = 0x2e,
/// <summary>Indicates an <see cref="IDefaultValueExpression"/>.</summary>
DefaultValueExpression = 0x2f,
ArrayCreationExpression = 0x114,
/// <summary>Indicates an <see cref="IInstanceReferenceExpression"/>.</summary>
InstanceReferenceExpression = 0x30,
/// <summary>Indicates an <see cref="IIsExpression"/>.</summary>
IsExpression = 0x33,
// TypeOperationExpression = 0x34,
AwaitExpression = 0x35,
/// <summary>Indicates an <see cref="IAddressOfExpression"/>.</summary>
AddressOfExpression = 0x36,
InstanceReferenceExpression = 0x115,
/// <summary>Indicates an <see cref="IIsTypeExpression"/>.</summary>
IsTypeExpression = 0x116,
/// <summary>Indicates an <see cref="IAwaitExpression"/>.</summary>
AwaitExpression = 0x117,
/// <summary>Indicates an <see cref="IAssignmentExpression"/>.</summary>
AssignmentExpression = 0x37,
AssignmentExpression = 0x118,
/// <summary>Indicates an <see cref="ICompoundAssignmentExpression"/>.</summary>
CompoundAssignmentExpression = 0x38,
CompoundAssignmentExpression = 0x119,
/// <summary>Indicates an <see cref="IParenthesizedExpression"/>.</summary>
ParenthesizedExpression = 0x39,
/// <summary>Indicates an <see cref="IUnboundLambdaExpression"/>.</summary>
UnboundLambdaExpression = 0x3a,
ParenthesizedExpression = 0x11a,
/// <summary>Indicates an <see cref="IEventAssignmentExpression"/>.</summary>
EventAssignmentExpression = 0x3b,
EventAssignmentExpression = 0x11b,
/// <summary>Indicates an <see cref="IConditionalAccessExpression"/>.</summary>
ConditionalAccessExpression = 0x11c,
/// <summary>Indicates an <see cref="IConditionalAccessInstanceExpression"/>.</summary>
ConditionalAccessInstanceExpression = 0x11d,
// Expressions that occur only in C#.
/// <summary>Indicates an <see cref="IDefaultValueExpression"/>.</summary>
DefaultValueExpression = 0x200,
/// <summary>Indicates an <see cref="ITypeOfExpression"/>.</summary>
TypeOfExpression = 0x34,
TypeOfExpression = 0x201,
/// <summary>Indicates an <see cref="ISizeOfExpression"/>.</summary>
SizeOfExpression = 0x50,
SizeOfExpression = 0x202,
/// <summary>Indicates an <see cref="IAddressOfExpression"/>.</summary>
AddressOfExpression = 0x203,
/// <summary>Indicates an <see cref="IPointerIndirectionReferenceExpression"/>.</summary>
PointerIndirectionReferenceExpression = 0x204,
/// <summary>Indicates an <see cref="IUnboundLambdaExpression"/>.</summary>
UnboundLambdaExpression = 0x205,
/// <summary>Indicates an <see cref="IIncrementExpression"/>.</summary>
IncrementExpression = 0x206,
// VB only
// Expressions that occur only in Visual Basic.
/// <summary>Indicates an <see cref="IOmittedArgumentExpression"/>.</summary>
OmittedArgumentExpression = 0x3c,
/// <summary>Indicates an <see cref="IStopStatement"/>.</summary>
StopStatement = 0x3d,
/// <summary>Indicates an <see cref="IEndStatement"/>.</summary>
EndStatement = 0x3e,
/// <summary>Indicates an <see cref="IWithStatement"/>.</summary>
WithStatement = 0x3f,
// Newly added
OmittedArgumentExpression = 0x300,
/// <summary>Indicates an <see cref="ILateBoundMemberReferenceExpression"/>.</summary>
LateBoundMemberReferenceExpression = 0x301,
/// <summary>Indicates an <see cref="IPlaceholderExpression"/>.</summary>
PlaceholderExpression = 0x302,
/// <summary>Indicates an <see cref="IConditionalAccessExpression"/>.</summary>
ConditionalAccessExpression = 0x40,
/// <summary>Indicates an <see cref="IIncrementExpression"/>.</summary>
IncrementExpression = 0x41,
// Operations that are constituents of statements, expressions, or declarations.
/// <summary>Indicates an <see cref="IArgument"/>.</summary>
Argument = 0x42,
/// <summary>Indicates an <see cref="IFieldInitializer"/>.</summary>
FieldInitializerInCreation = 0x43,
FieldInitializerInCreation = 0x400,
/// <summary>Indicates an <see cref="IFieldInitializer"/>.</summary>
FieldInitializerAtDeclaration = 0x401,
/// <summary>Indicates an <see cref="IPropertyInitializer"/>.</summary>
PropertyInitializerInCreation = 0x44,
PropertyInitializerInCreation = 0x402,
/// <summary>Indicates an <see cref="IPropertyInitializer"/>.</summary>
PropertyInitializerAtDeclaration = 0x403,
/// <summary>Indicates an <see cref="IParameterInitializer"/>.</summary>
ParameterInitializerAtDeclaration = 0x404,
/// <summary>Indicates an <see cref="IArrayInitializer"/>.</summary>
ArrayInitializer = 0x45,
ArrayInitializer = 0x405,
/// <summary>Indicates an <see cref="IVariableDeclaration"/>.</summary>
VariableDeclaration = 0x46,
VariableDeclaration = 0x406,
/// <summary>Indicates an <see cref="IArgument"/>.</summary>
Argument = 0x407,
/// <summary>Indicates an <see cref="ICatchClause"/>.</summary>
CatchClause = 0x408,
/// <summary>Indicates an <see cref="ISwitchCase"/>.</summary>
SwitchCase = 0x47,
SwitchCase = 0x409,
/// <summary>Indicates an <see cref="ISingleValueCaseClause"/>.</summary>
SingleValueCaseClause = 0x48,
SingleValueCaseClause = 0x40a,
/// <summary>Indicates an <see cref="IRelationalCaseClause"/>.</summary>
RelationalCaseClause = 0x49,
RelationalCaseClause = 0x40b,
/// <summary>Indicates an <see cref="IRangeCaseClause"/>.</summary>
RangeCaseClause = 0x4a,
/// <summary>Indicates an <see cref="IParameterInitializer"/>.</summary>
ParameterInitializerAtDeclaration = 0x4b,
/// <summary>Indicates an <see cref="IFieldInitializer"/>.</summary>
FieldInitializerAtDeclaration = 0x4c,
/// <summary>Indicates an <see cref="IPropertyInitializer"/>.</summary>
PropertyInitializerAtDeclaration = 0x4d
RangeCaseClause = 0x40c,
}
}
......@@ -397,30 +397,18 @@ public interface IUsingStatement : IOperation
/// Body of the using, over which the resources of the using are maintained.
/// </summary>
IOperation Body { get; }
}
/// <summary>
/// Represents a C# using or VB Using statement that declares one or more local variables for the resources held by the using.
/// </summary>
public interface IUsingWithDeclarationStatement : IUsingStatement
{
/// <summary>
/// Declaration of variables introduced by the using.
/// Declaration introduced by the using statement. Null if the using statement does not declare any variables.
/// </summary>
IVariableDeclarationStatement Declaration { get; }
}
/// <summary>
/// Represents a C# using or VB Using statement that uses an expression for the resource held by the using.
/// </summary>
public interface IUsingWithExpressionStatement : IUsingStatement
{
/// <summary>
/// Resource held by the using.
/// Resource held by the using. Can be null if Declaration is not null.
/// </summary>
IOperation Value { get; }
}
/// <summary>
/// Represents a C# fixed staement.
/// </summary>
......
......@@ -130,12 +130,7 @@ public virtual void VisitCatch(ICatchClause operation)
DefaultVisit(operation);
}
public virtual void VisitUsingWithDeclarationStatement(IUsingWithDeclarationStatement operation)
{
DefaultVisit(operation);
}
public virtual void VisitUsingWithExpressionStatement(IUsingWithExpressionStatement operation)
public virtual void VisitUsingStatement(IUsingStatement operation)
{
DefaultVisit(operation);
}
......@@ -240,6 +235,21 @@ public virtual void VisitConditionalAccessExpression(IConditionalAccessExpressio
DefaultVisit(operation);
}
public virtual void VisitConditionalAccessInstanceExpression(IConditionalAccessInstanceExpression operation)
{
DefaultVisit(operation);
}
public virtual void VisitPlaceholderExpression(IPlaceholderExpression operation)
{
DefaultVisit(operation);
}
public virtual void VisitIndexedPropertyReferenceExpression(IIndexedPropertyReferenceExpression operation)
{
DefaultVisit(operation);
}
public virtual void VisitUnaryOperatorExpression(IUnaryOperatorExpression operation)
{
DefaultVisit(operation);
......@@ -265,7 +275,7 @@ public virtual void VisitNullCoalescingExpression(INullCoalescingExpression oper
DefaultVisit(operation);
}
public virtual void VisitIsExpression(IIsExpression operation)
public virtual void VisitIsTypeExpression(IIsTypeExpression operation)
{
DefaultVisit(operation);
}
......@@ -515,16 +525,11 @@ public virtual TResult VisitCatch(ICatchClause operation, TArgument argument)
return DefaultVisit(operation, argument);
}
public virtual TResult VisitUsingWithDeclarationStatement(IUsingWithDeclarationStatement operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitUsingWithExpressionStatement(IUsingWithExpressionStatement operation, TArgument argument)
public virtual TResult VisitUsingStatement(IUsingStatement operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitFixedStatement(IFixedStatement operation, TArgument argument)
{
return DefaultVisit(operation, argument);
......@@ -625,6 +630,21 @@ public virtual TResult VisitConditionalAccessExpression(IConditionalAccessExpres
return DefaultVisit(operation, argument);
}
public virtual TResult VisitConditionalAccessInstanceExpression(IConditionalAccessInstanceExpression operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitPlaceholderExpression(IPlaceholderExpression operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitIndexedPropertyReferenceExpression(IIndexedPropertyReferenceExpression operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitUnaryOperatorExpression(IUnaryOperatorExpression operation, TArgument argument)
{
return DefaultVisit(operation, argument);
......@@ -650,7 +670,7 @@ public virtual TResult VisitNullCoalescingExpression(INullCoalescingExpression o
return DefaultVisit(operation, argument);
}
public virtual TResult VisitIsExpression(IIsExpression operation, TArgument argument)
public virtual TResult VisitIsTypeExpression(IIsTypeExpression operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
......
......@@ -161,13 +161,9 @@ public override void VisitCatch(ICatchClause operation)
Visit(operation.Handler);
}
public override void VisitUsingWithDeclarationStatement(IUsingWithDeclarationStatement operation)
public override void VisitUsingStatement(IUsingStatement operation)
{
Visit(operation.Declaration);
}
public override void VisitUsingWithExpressionStatement(IUsingWithExpressionStatement operation)
{
Visit(operation.Value);
}
......@@ -261,7 +257,22 @@ public override void VisitEventAssignmentExpression(IEventAssignmentExpression o
public override void VisitConditionalAccessExpression(IConditionalAccessExpression operation)
{
Visit(operation.Access);
Visit(operation.ConditionalValue);
Visit(operation.ConditionalInstance);
}
public override void VisitConditionalAccessInstanceExpression(IConditionalAccessInstanceExpression operation)
{
}
public override void VisitPlaceholderExpression(IPlaceholderExpression operation)
{
}
public override void VisitIndexedPropertyReferenceExpression(IIndexedPropertyReferenceExpression operation)
{
Visit(operation.Instance);
VisitArray(operation.ArgumentsInParameterOrder);
}
public override void VisitUnaryOperatorExpression(IUnaryOperatorExpression operation)
......@@ -271,8 +282,8 @@ public override void VisitUnaryOperatorExpression(IUnaryOperatorExpression opera
public override void VisitBinaryOperatorExpression(IBinaryOperatorExpression operation)
{
Visit(operation.Left);
Visit(operation.Right);
Visit(operation.LeftOperand);
Visit(operation.RightOperand);
}
public override void VisitConversionExpression(IConversionExpression operation)
......@@ -289,11 +300,11 @@ public override void VisitConditionalChoiceExpression(IConditionalChoiceExpressi
public override void VisitNullCoalescingExpression(INullCoalescingExpression operation)
{
Visit(operation.Primary);
Visit(operation.Secondary);
Visit(operation.PrimaryOperand);
Visit(operation.SecondaryOperand);
}
public override void VisitIsExpression(IIsExpression operation)
public override void VisitIsTypeExpression(IIsTypeExpression operation)
{
Visit(operation.Operand);
}
......
......@@ -174,53 +174,23 @@ string Cci.INamedEntity.Name
/// <summary>
/// A fake containing assembly for an ErrorType object.
/// </summary>
private class ErrorAssembly : Cci.IAssemblyReference
private sealed class ErrorAssembly : Cci.IAssemblyReference
{
public static readonly ErrorAssembly Singleton = new ErrorAssembly();
/// <summary>
/// For the name we will use a word "Error" followed by a guid, generated on the spot.
/// </summary>
private static readonly string s_name = "Error" + Guid.NewGuid().ToString("B");
private static readonly AssemblyIdentity s_identity = new AssemblyIdentity(
name: "Error" + Guid.NewGuid().ToString("B"),
version: AssemblyIdentity.NullVersion,
cultureName: "",
publicKeyOrToken: ImmutableArray<byte>.Empty,
hasPublicKey: false,
isRetargetable: false,
contentType: AssemblyContentType.Default);
string Cci.IAssemblyReference.Culture
{
get
{
return "";
}
}
bool Cci.IAssemblyReference.IsRetargetable
{
get
{
return false;
}
}
AssemblyContentType Cci.IAssemblyReference.ContentType
{
get
{
return AssemblyContentType.Default;
}
}
ImmutableArray<byte> Cci.IAssemblyReference.PublicKeyToken
{
get
{
return ImmutableArray<byte>.Empty;
}
}
Version Cci.IAssemblyReference.Version
{
get
{
return AssemblyIdentity.NullVersion;
}
}
AssemblyIdentity Cci.IAssemblyReference.Identity => s_identity;
Cci.IAssemblyReference Cci.IModuleReference.GetContainingAssembly(EmitContext context)
{
......@@ -242,18 +212,7 @@ Cci.IDefinition Cci.IReference.AsDefinition(EmitContext context)
return null;
}
public string GetDisplayName()
{
return s_name;
}
string Cci.INamedEntity.Name
{
get
{
return s_name;
}
}
string Cci.INamedEntity.Name => s_identity.Name;
}
}
}
......@@ -469,7 +469,7 @@ private void DefineAssemblyReferenceAliases()
{
foreach (AssemblyReferenceAlias alias in Module.GetAssemblyReferenceAliases(Context))
{
UsingNamespace("Z" + alias.Name + " " + alias.Assembly.GetDisplayName(), Module);
UsingNamespace("Z" + alias.Name + " " + alias.Assembly.Identity.GetDisplayName(), Module);
}
}
......
......@@ -2568,16 +2568,18 @@ private void PopulateAssemblyRefTableRows()
foreach (var assemblyRef in assemblyRefs)
{
AssemblyRefTableRow r = new AssemblyRefTableRow();
r.Version = assemblyRef.Version;
r.PublicKeyToken = heaps.GetBlobIndex(assemblyRef.PublicKeyToken);
var identity = assemblyRef.Identity;
r.Version = identity.Version;
r.PublicKeyToken = heaps.GetBlobIndex(identity.PublicKeyToken);
Debug.Assert(!string.IsNullOrEmpty(assemblyRef.Name));
r.Name = this.GetStringIndexForPathAndCheckLength(assemblyRef.Name, assemblyRef);
r.Culture = heaps.GetStringIndex(assemblyRef.Culture);
r.Culture = heaps.GetStringIndex(identity.CultureName);
r.IsRetargetable = assemblyRef.IsRetargetable;
r.ContentType = assemblyRef.ContentType;
r.IsRetargetable = identity.IsRetargetable;
r.ContentType = identity.ContentType;
_assemblyRefTable.Add(r);
}
}
......@@ -2594,24 +2596,12 @@ protected sealed class AssemblyReferenceComparer : IEqualityComparer<IAssemblyRe
public bool Equals(IAssemblyReference x, IAssemblyReference y)
{
if (ReferenceEquals(x, y))
{
return true;
}
return
x.Version.Equals(y.Version) &&
ByteSequenceComparer.Equals(x.PublicKeyToken, y.PublicKeyToken) &&
x.Name == y.Name &&
x.Culture == y.Culture;
return x.Identity == y.Identity;
}
public int GetHashCode(IAssemblyReference reference)
{
return Hash.Combine(reference.Version,
Hash.Combine(ByteSequenceComparer.GetHashCode(reference.PublicKeyToken),
Hash.Combine(reference.Name.GetHashCode(),
Hash.Combine(reference.Culture, 0))));
return reference.Identity.GetHashCode();
}
}
......@@ -2627,7 +2617,7 @@ private void PopulateAssemblyTableRows()
IAssembly assembly = this.module.AsAssembly;
_assemblyKey = heaps.GetBlobIndex(assembly.PublicKey);
_assemblyName = this.GetStringIndexForPathAndCheckLength(assembly.Name, assembly);
_assemblyCulture = heaps.GetStringIndex(assembly.Culture);
_assemblyCulture = heaps.GetStringIndex(assembly.Identity.CultureName);
}
private BlobIdx _assemblyKey;
......@@ -4118,11 +4108,13 @@ private void SerializeAssemblyTable(BlobBuilder writer, MetadataSizes metadataSi
}
IAssembly assembly = this.module.AsAssembly;
var identity = assembly.Identity;
writer.WriteUInt32((uint)assembly.HashAlgorithm);
writer.WriteUInt16((ushort)assembly.Version.Major);
writer.WriteUInt16((ushort)assembly.Version.Minor);
writer.WriteUInt16((ushort)assembly.Version.Build);
writer.WriteUInt16((ushort)assembly.Version.Revision);
writer.WriteUInt16((ushort)identity.Version.Major);
writer.WriteUInt16((ushort)identity.Version.Minor);
writer.WriteUInt16((ushort)identity.Version.Build);
writer.WriteUInt16((ushort)identity.Version.Revision);
writer.WriteUInt32(assembly.Flags);
writer.WriteReference((uint)heaps.ResolveBlobIndex(_assemblyKey), metadataSizes.BlobIndexSize);
......@@ -4948,13 +4940,15 @@ private void SerializeTypeName(ITypeReference typeReference, BlobBuilder writer)
/// </summary>
internal static string StrongName(IAssemblyReference assemblyReference)
{
var identity = assemblyReference.Identity;
var pooled = PooledStringBuilder.GetInstance();
StringBuilder sb = pooled.Builder;
sb.Append(assemblyReference.Name);
sb.AppendFormat(CultureInfo.InvariantCulture, ", Version={0}.{1}.{2}.{3}", assemblyReference.Version.Major, assemblyReference.Version.Minor, assemblyReference.Version.Build, assemblyReference.Version.Revision);
if (!string.IsNullOrEmpty(assemblyReference.Culture))
sb.Append(identity.Name);
sb.AppendFormat(CultureInfo.InvariantCulture, ", Version={0}.{1}.{2}.{3}", identity.Version.Major, identity.Version.Minor, identity.Version.Build, identity.Version.Revision);
if (!string.IsNullOrEmpty(identity.CultureName))
{
sb.AppendFormat(CultureInfo.InvariantCulture, ", Culture={0}", assemblyReference.Culture);
sb.AppendFormat(CultureInfo.InvariantCulture, ", Culture={0}", identity.CultureName);
}
else
{
......@@ -4962,9 +4956,9 @@ internal static string StrongName(IAssemblyReference assemblyReference)
}
sb.Append(", PublicKeyToken=");
if (assemblyReference.PublicKeyToken.Length > 0)
if (identity.PublicKeyToken.Length > 0)
{
foreach (byte b in assemblyReference.PublicKeyToken)
foreach (byte b in identity.PublicKeyToken)
{
sb.Append(b.ToString("x2"));
}
......@@ -4974,18 +4968,18 @@ internal static string StrongName(IAssemblyReference assemblyReference)
sb.Append("null");
}
if (assemblyReference.IsRetargetable)
if (identity.IsRetargetable)
{
sb.Append(", Retargetable=Yes");
}
if (assemblyReference.ContentType == AssemblyContentType.WindowsRuntime)
if (identity.ContentType == AssemblyContentType.WindowsRuntime)
{
sb.Append(", ContentType=WindowsRuntime");
}
else
{
Debug.Assert(assemblyReference.ContentType == AssemblyContentType.Default);
Debug.Assert(identity.ContentType == AssemblyContentType.Default);
}
return pooled.ToStringAndFree();
......
......@@ -51,34 +51,7 @@ internal interface IAssembly : IModule, IAssemblyReference
/// </summary>
internal interface IAssemblyReference : IModuleReference
{
/// <summary>
/// Identifies the culture associated with the assembly reference. Typically specified for satellite assemblies with localized resources.
/// Empty if not specified.
/// </summary>
string Culture { get; }
/// <summary>
/// True if the implementation of the referenced assembly used at runtime is not expected to match the version seen at compile time.
/// </summary>
bool IsRetargetable { get; }
/// <summary>
/// Type of code contained in an assembly. Determines assembly binding model.
/// </summary>
AssemblyContentType ContentType { get; }
/// <summary>
/// The hashed 8 bytes of the public key of the referenced assembly.
/// Empty if the referenced assembly does not have a public key.
/// </summary>
ImmutableArray<byte> PublicKeyToken { get; }
/// <summary>
/// The version of the assembly reference.
/// </summary>
Version Version { get; }
string GetDisplayName();
AssemblyIdentity Identity { get; }
}
/// <summary>
......
......@@ -17,7 +17,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
_targetAssembly = assemblySymbol
End Sub
Public ReadOnly Property MetadataIdentity As AssemblyIdentity
Public ReadOnly Property Identity As AssemblyIdentity Implements Cci.IAssemblyReference.Identity
Get
Return _targetAssembly.Identity
End Get
......@@ -27,43 +27,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
visitor.Visit(DirectCast(Me, Cci.IAssemblyReference))
End Sub
Private ReadOnly Property IAssemblyReferenceCulture As String Implements Cci.IAssemblyReference.Culture
Get
Return MetadataIdentity.CultureName
End Get
End Property
Private ReadOnly Property IAssemblyReferenceIsRetargetable As Boolean Implements Cci.IAssemblyReference.IsRetargetable
Get
Return MetadataIdentity.IsRetargetable
End Get
End Property
Private ReadOnly Property IAssemblyReferenceContentType As AssemblyContentType Implements Cci.IAssemblyReference.ContentType
Get
Return MetadataIdentity.ContentType
End Get
End Property
Private ReadOnly Property IAssemblyReferencePublicKeyToken As ImmutableArray(Of Byte) Implements Cci.IAssemblyReference.PublicKeyToken
Get
Return MetadataIdentity.PublicKeyToken
End Get
End Property
Private ReadOnly Property IAssemblyReferenceVersion As Version Implements Cci.IAssemblyReference.Version
Get
Return MetadataIdentity.Version
End Get
End Property
Private Function IAssemblyReferenceGetDisplayName() As String Implements Cci.IAssemblyReference.GetDisplayName
Return MetadataIdentity.GetDisplayName()
End Function
Private ReadOnly Property INamedEntityName As String Implements Cci.INamedEntity.Name
Get
Return MetadataIdentity.Name
Return Identity.Name
End Get
End Property
......
......@@ -135,40 +135,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Next
End Sub
Private ReadOnly Property IAssemblyReferenceCulture As String Implements Cci.IAssemblyReference.Culture
Private ReadOnly Property Identity As AssemblyIdentity Implements Cci.IAssembly.Identity
Get
Return m_SourceAssembly.Identity.CultureName
Return m_SourceAssembly.Identity
End Get
End Property
Private ReadOnly Property IAssemblyReferenceIsRetargetable As Boolean Implements Cci.IAssemblyReference.IsRetargetable
Get
Return m_SourceAssembly.Identity.IsRetargetable
End Get
End Property
Private ReadOnly Property IAssemblyReferenceContentType As AssemblyContentType Implements Cci.IAssemblyReference.ContentType
Get
Return m_SourceAssembly.Identity.ContentType
End Get
End Property
Private ReadOnly Property IAssemblyReferencePublicKeyToken As ImmutableArray(Of Byte) Implements Cci.IAssemblyReference.PublicKeyToken
Get
Return m_SourceAssembly.Identity.PublicKeyToken
End Get
End Property
Private ReadOnly Property IAssemblyReferenceVersion As Version Implements Cci.IAssemblyReference.Version
Get
Return m_SourceAssembly.Identity.Version
End Get
End Property
Private Function IAssemblyReferenceGetDisplayName() As String Implements Cci.IAssemblyReference.GetDisplayName
Return m_SourceAssembly.Identity.GetDisplayName()
End Function
Friend Overrides ReadOnly Property Name As String
Get
Return _metadataName
......
......@@ -139,10 +139,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Private Sub ValidateReferencedAssembly(assembly As AssemblySymbol, asmRef As AssemblyReference, diagnostics As DiagnosticBag)
Dim asmIdentity As AssemblyIdentity = SourceModule.ContainingAssembly.Identity
Dim refIdentity As AssemblyIdentity = asmRef.MetadataIdentity
Dim refIdentity As AssemblyIdentity = asmRef.Identity
If asmIdentity.IsStrongName AndAlso Not refIdentity.IsStrongName AndAlso
DirectCast(asmRef, Cci.IAssemblyReference).ContentType <> Reflection.AssemblyContentType.WindowsRuntime Then
asmRef.Identity.ContentType <> Reflection.AssemblyContentType.WindowsRuntime Then
' Dev12 reported error, we have changed it to a warning to allow referencing libraries
' built for platforms that don't support strong names.
diagnostics.Add(ErrorFactory.ErrorInfo(ERRID.WRN_ReferencedAssemblyDoesNotHaveStrongName, assembly), NoLocation.Singleton)
......
......@@ -126,19 +126,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Shared Function DefaultErrorFormat(symbol As Symbol) As FormattedSymbol
Return New FormattedSymbol(symbol, SymbolDisplayFormat.VisualBasicErrorMessageFormat)
End Function
Public Shared Function DefaultErrorFormatIfSpecialType(arg As Object) As Object
Dim symbol = TryCast(arg, Symbol)
If symbol Is Nothing Then
Return arg
End If
If TypeOf symbol Is TypeSymbol AndAlso DirectCast(symbol, TypeSymbol).SpecialType <> SpecialType.None Then
Return DefaultErrorFormat(symbol)
End If
Return symbol
End Function
End Class
End Namespace
......@@ -50,7 +50,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Dim containingAssembly As AssemblySymbol = Me.ContainingAssembly
If containingAssembly.IsMissing Then
Return ErrorFactory.ErrorInfo(ERRID.ERR_UnreferencedAssembly3, containingAssembly.Identity, CustomSymbolDisplayFormatter.DefaultErrorFormatIfSpecialType(Me))
Dim arg = If(Me.SpecialType <> SpecialType.None, DirectCast(CustomSymbolDisplayFormatter.DefaultErrorFormat(Me), Object), Me)
Return ErrorFactory.ErrorInfo(ERRID.ERR_UnreferencedAssembly3, containingAssembly.Identity, arg)
Else
Dim containingModule As ModuleSymbol = Me.ContainingModule
......
......@@ -1548,5 +1548,100 @@ End Class
Diagnostic(NullOperationSyntaxTestAnalyzer.ParamsArrayOperationDescriptor.Id, "New Integer() { 1 }").WithLocation(10, 12),
Diagnostic(NullOperationSyntaxTestAnalyzer.ParamsArrayOperationDescriptor.Id, "New Integer() { 1, 2 }").WithLocation(11, 12))
End Sub
<WorkItem(8114, "https://github.com/dotnet/roslyn/issues/8114")>
<Fact>
Public Sub InvalidOperatorVisualBasic()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Public Function M1(a As Double, b as C) as Double
Return b + c
End Sub
Public Function M2(s As C) As C
Return -s
End Function
End Class
]]>
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics(
Diagnostic(ERRID.ERR_EndFunctionExpected, "Public Function M1(a As Double, b as C) as Double").WithLocation(2, 5),
Diagnostic(ERRID.ERR_InvalidEndSub, "End Sub").WithLocation(4, 5),
Diagnostic(ERRID.ERR_InvInsideEndsProc, "Public Function M2(s As C) As C").WithLocation(6, 5),
Diagnostic(ERRID.ERR_ClassNotExpression1, "c").WithArguments("C").WithLocation(3, 20),
Diagnostic(ERRID.ERR_UnaryOperand2, "-s").WithArguments("-", "C").WithLocation(7, 16))
comp.VerifyAnalyzerDiagnostics({New InvalidOperatorExpressionTestAnalyzer}, Nothing, Nothing, False,
Diagnostic(InvalidOperatorExpressionTestAnalyzer.InvalidBinaryDescriptor.Id, "b + c").WithLocation(3, 16),
Diagnostic(InvalidOperatorExpressionTestAnalyzer.InvalidUnaryDescriptor.Id, "-s").WithLocation(7, 16))
End Sub
<Fact>
Public Sub ConditionalAccessOperationsVisualBasic()
Dim source = <compilation>
<file name="c.vb">
<![CDATA[
Class C
Public Property Prop As Integer
Get
Return 0
End Get
Set
End Set
End Property
Public Field As Integer
Default Public Property Mumble(i As Integer)
Get
return Field
End Get
Set
Field = Value
End Set
End Property
Public Field1 As C = Nothing
Public Sub M0(p As C)
Dim x = p?.Prop
x = p?.Field
x = p?(0)
p?.M0(Nothing)
x = Field1?.Prop
x = Field1?.Field
x = Field1?(0)
Field1?.M0(Nothing)
End Sub
End Class
]]>
</file>
</compilation>
Dim comp = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New ConditionalAccessOperationTestAnalyzer}, Nothing, Nothing, False,
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?.Prop").WithLocation(24, 17),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p?.Prop").WithLocation(24, 17),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?.Field").WithLocation(25, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p?.Field").WithLocation(25, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?(0)").WithLocation(26, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p?(0)").WithLocation(26, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "p?.M0(Nothing)").WithLocation(27, 9),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "p?.M0(Nothing)").WithLocation(27, 9),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?.Prop").WithLocation(29, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1?.Prop").WithLocation(29, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?.Field").WithLocation(30, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1?.Field").WithLocation(30, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?(0)").WithLocation(31, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1?(0)").WithLocation(31, 13),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessOperationDescriptor.Id, "Field1?.M0(Nothing)").WithLocation(32, 9),
Diagnostic(ConditionalAccessOperationTestAnalyzer.ConditionalAccessInstanceOperationDescriptor.Id, "Field1?.M0(Nothing)").WithLocation(32, 9))
End Sub
End Class
End Namespace
......@@ -14,8 +14,6 @@
<OutputType>Library</OutputType>
<RootNamespace>Microsoft.CodeAnalysis.Editor</RootNamespace>
<AssemblyName>Microsoft.CodeAnalysis.EditorFeatures</AssemblyName>
<!-- Disable the architecture mismatch warning -->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<CopyNuGetImplementations>false</CopyNuGetImplementations>
</PropertyGroup>
......@@ -820,4 +818,4 @@
<ImportGroup Label="Targets">
<Import Project="..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -10,8 +10,6 @@
<OutputType>Library</OutputType>
<RootNamespace>Microsoft.CodeAnalysis.Text</RootNamespace>
<AssemblyName>Microsoft.CodeAnalysis.EditorFeatures.Text</AssemblyName>
<!-- Disable the architecture mismatch warning -->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<CopyNuGetImplementations>false</CopyNuGetImplementations>
</PropertyGroup>
......
......@@ -19,40 +19,8 @@ internal AssemblyReference(AssemblyIdentity identity)
_identity = identity;
}
AssemblyContentType IAssemblyReference.ContentType
{
get { return _identity.ContentType; }
}
string IAssemblyReference.Culture
{
get { return _identity.CultureName; }
}
bool IAssemblyReference.IsRetargetable
{
get { return _identity.IsRetargetable; }
}
string INamedEntity.Name
{
get { return _identity.Name; }
}
ImmutableArray<byte> IAssemblyReference.PublicKeyToken
{
get { return _identity.PublicKeyToken; }
}
Version IAssemblyReference.Version
{
get { return _identity.Version; }
}
string IAssemblyReference.GetDisplayName()
{
return _identity.GetDisplayName();
}
AssemblyIdentity IAssemblyReference.Identity => _identity;
string INamedEntity.Name => _identity.Name;
IAssemblyReference IModuleReference.GetContainingAssembly(EmitContext context)
{
......
......@@ -84,14 +84,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (allSymbolReferences.Count == 0)
{
// No exact matches found. Fall back to fuzzy searching.
// Only bother doing this for host workspaces. We don't want this for
// things like the Interactive workspace as this will cause us to
// create expensive bktrees which we won't even be able to save for
// future use.
if (document.Project.Solution.Workspace.Kind == WorkspaceKind.Host)
{
await FindResults(projectToAssembly, referenceToCompilation, project, allSymbolReferences, finder, exact: false, cancellationToken: cancellationToken).ConfigureAwait(false);
}
await FindResults(projectToAssembly, referenceToCompilation, project, allSymbolReferences, finder, exact: false, cancellationToken: cancellationToken).ConfigureAwait(false);
}
// Nothing found at all. No need to proceed.
......
......@@ -10,8 +10,6 @@
<OutputType>Library</OutputType>
<RootNamespace>Microsoft.CodeAnalysis.Editor</RootNamespace>
<AssemblyName>Microsoft.CodeAnalysis.InteractiveEditorFeatures</AssemblyName>
<!-- Disable the architecture mismatch warning -->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<CopyNuGetImplementations>false</CopyNuGetImplementations>
</PropertyGroup>
......@@ -168,4 +166,4 @@
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -16,7 +16,7 @@ public BrowseObject(AnalyzerItem analyzerItem)
_analyzerItem = analyzerItem;
}
[DisplayName("(Name)")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.AnalyzerItemNameDisplayName))]
public string Name
{
get
......@@ -25,7 +25,7 @@ public string Name
}
}
[DisplayName("Path")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.AnalyzerItemPathDisplayName))]
public string Path
{
get
......
// 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.VisualStudio.LanguageServices.SolutionExplorer;
using System;
using System.ComponentModel;
using System.Globalization;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
{
/// <summary>
/// The attribute used for adding localized display names to properties
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
internal sealed class BrowseObjectDisplayNameAttribute : DisplayNameAttribute
{
private string m_key;
private bool m_initialized;
public BrowseObjectDisplayNameAttribute(string key)
{
m_key = key;
}
public override string DisplayName
{
get
{
if (!m_initialized)
{
base.DisplayNameValue = SolutionExplorerShim.ResourceManager.GetString(m_key, CultureInfo.CurrentUICulture);
m_initialized = true;
}
return base.DisplayName;
}
}
}
}
......@@ -20,7 +20,7 @@ public BrowseObject(DiagnosticItem diagnosticItem)
_diagnosticItem = diagnosticItem;
}
[DisplayName("ID")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemIDDisplayName))]
public string Id
{
get
......@@ -29,7 +29,7 @@ public string Id
}
}
[DisplayName("Title")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemTitleDisplayName))]
public string Title
{
get
......@@ -38,7 +38,7 @@ public string Title
}
}
[DisplayName("Description")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemDescriptionDisplayName))]
public string Description
{
get
......@@ -47,7 +47,7 @@ public string Description
}
}
[DisplayName("Help link")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemHelpLinkDisplayName))]
public string HelpLink
{
get
......@@ -56,7 +56,7 @@ public string HelpLink
}
}
[DisplayName("Category")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemCategoryDisplayName))]
public string Category
{
get
......@@ -65,7 +65,7 @@ public string Category
}
}
[DisplayName("Default severity")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemDefaultSeverityDisplayName))]
public string DefaultSeverity
{
get
......@@ -74,7 +74,7 @@ public string DefaultSeverity
}
}
[DisplayName("Enabled by default")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemEnabledByDefaultDisplayName))]
public bool EnabledByDefault
{
get
......@@ -83,7 +83,7 @@ public bool EnabledByDefault
}
}
[DisplayName("Message")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemMessageDisplayName))]
public string Message
{
get
......@@ -92,7 +92,7 @@ public string Message
}
}
[DisplayName("Tags")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemTagsDisplayName))]
public string Tags
{
get
......@@ -101,7 +101,7 @@ public string Tags
}
}
[DisplayName("Effective severity")]
[BrowseObjectDisplayName(nameof(SolutionExplorerShim.DiagnosticItemEffectiveSeverityDisplayName))]
public string EffectiveSeverity
{
get
......
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.0
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
......@@ -87,6 +87,24 @@ internal class SolutionExplorerShim {
}
}
/// <summary>
/// Looks up a localized string similar to (Name).
/// </summary>
internal static string AnalyzerItemNameDisplayName {
get {
return ResourceManager.GetString("AnalyzerItemNameDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Path.
/// </summary>
internal static string AnalyzerItemPathDisplayName {
get {
return ResourceManager.GetString("AnalyzerItemPathDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Checking out {0} for editing....
/// </summary>
......@@ -177,6 +195,96 @@ internal class SolutionExplorerShim {
}
}
/// <summary>
/// Looks up a localized string similar to Category.
/// </summary>
internal static string DiagnosticItemCategoryDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemCategoryDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Default severity.
/// </summary>
internal static string DiagnosticItemDefaultSeverityDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemDefaultSeverityDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Description.
/// </summary>
internal static string DiagnosticItemDescriptionDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemDescriptionDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Effective severity.
/// </summary>
internal static string DiagnosticItemEffectiveSeverityDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemEffectiveSeverityDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Enabled by default.
/// </summary>
internal static string DiagnosticItemEnabledByDefaultDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemEnabledByDefaultDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Help link.
/// </summary>
internal static string DiagnosticItemHelpLinkDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemHelpLinkDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ID.
/// </summary>
internal static string DiagnosticItemIDDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemIDDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Message.
/// </summary>
internal static string DiagnosticItemMessageDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemMessageDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tags.
/// </summary>
internal static string DiagnosticItemTagsDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemTagsDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Title.
/// </summary>
internal static string DiagnosticItemTitleDisplayName {
get {
return ResourceManager.GetString("DiagnosticItemTitleDisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Default.
/// </summary>
......
......@@ -112,6 +112,7 @@
<Compile Include="AnalyzersFolderItem\AnalyzersFolderItemSource.cs" />
<Compile Include="AnalyzersFolderItem\AnalyzersFolderItemProvider.cs" />
<Compile Include="BaseItem.cs" />
<Compile Include="BrowseObjectAttributes.cs" />
<Compile Include="DiagnosticItem\DiagnosticItem.BrowseObject.cs" />
<Compile Include="DiagnosticItem\DiagnosticItemProvider.cs" />
<Compile Include="AnalyzerReferenceManager.cs" />
......
......@@ -174,4 +174,40 @@
<data name="AnalyzersCommandHandler_CheckingOutRuleSet" xml:space="preserve">
<value>Checking out {0} for editing...</value>
</data>
<data name="AnalyzerItemNameDisplayName" xml:space="preserve">
<value>(Name)</value>
</data>
<data name="AnalyzerItemPathDisplayName" xml:space="preserve">
<value>Path</value>
</data>
<data name="DiagnosticItemCategoryDisplayName" xml:space="preserve">
<value>Category</value>
</data>
<data name="DiagnosticItemDefaultSeverityDisplayName" xml:space="preserve">
<value>Default severity</value>
</data>
<data name="DiagnosticItemDescriptionDisplayName" xml:space="preserve">
<value>Description</value>
</data>
<data name="DiagnosticItemEffectiveSeverityDisplayName" xml:space="preserve">
<value>Effective severity</value>
</data>
<data name="DiagnosticItemEnabledByDefaultDisplayName" xml:space="preserve">
<value>Enabled by default</value>
</data>
<data name="DiagnosticItemHelpLinkDisplayName" xml:space="preserve">
<value>Help link</value>
</data>
<data name="DiagnosticItemIDDisplayName" xml:space="preserve">
<value>ID</value>
</data>
<data name="DiagnosticItemMessageDisplayName" xml:space="preserve">
<value>Message</value>
</data>
<data name="DiagnosticItemTagsDisplayName" xml:space="preserve">
<value>Tags</value>
</data>
<data name="DiagnosticItemTitleDisplayName" xml:space="preserve">
<value>Title</value>
</data>
</root>
\ No newline at end of file
......@@ -25,7 +25,7 @@ internal partial class SymbolTreeInfo
/// <summary>
/// The spell checker we use for fuzzy match queries.
/// </summary>
private readonly Lazy<SpellChecker> _lazySpellChecker;
private readonly SpellChecker _spellChecker;
private static readonly StringComparer s_caseInsensitiveComparer = CaseInsensitiveComparison.Comparer;
......@@ -45,25 +45,11 @@ internal partial class SymbolTreeInfo
: StringComparer.Ordinal.Compare(s1, s2);
};
private SymbolTreeInfo(VersionStamp version, IReadOnlyList<Node> orderedNodes)
: this(version, orderedNodes, new Lazy<SpellChecker>(() => new SpellChecker(orderedNodes.Select(n => n.Name))))
{
}
private SymbolTreeInfo(VersionStamp version, IReadOnlyList<Node> orderedNodes, SpellChecker spellChecker)
: this(version, orderedNodes, new Lazy<SpellChecker>(() => spellChecker))
{
// Make the lazy 'Created'. This is a no-op since we already have the underlying spell
// checker. This way if we end up wanting to serialize this tree info, we'll also
// serialize the spell checker.
var unused = _lazySpellChecker.Value;
}
private SymbolTreeInfo(VersionStamp version, IReadOnlyList<Node> orderedNodes, Lazy<SpellChecker> lazySpellChecker)
{
_version = version;
_nodes = orderedNodes;
_lazySpellChecker = lazySpellChecker;
_spellChecker = spellChecker;
}
public int Count => _nodes.Count;
......@@ -98,7 +84,7 @@ public Task<IEnumerable<ISymbol>> FindAsync(SearchQuery query, AsyncLazy<IAssemb
/// </summary>
public async Task<IEnumerable<ISymbol>> FuzzyFindAsync(AsyncLazy<IAssemblySymbol> lazyAssembly, string name, CancellationToken cancellationToken)
{
var similarNames = _lazySpellChecker.Value.FindSimilarWords(name);
var similarNames = _spellChecker.FindSimilarWords(name);
var result = new List<ISymbol>();
foreach (var similarName in similarNames)
......@@ -305,7 +291,8 @@ internal static SymbolTreeInfo Create(VersionStamp version, IAssemblySymbol asse
var list = new List<Node>();
GenerateNodes(assembly.GlobalNamespace, list);
return new SymbolTreeInfo(version, SortNodes(list));
var spellChecker = new SpellChecker(list.Select(n => n.Name));
return new SymbolTreeInfo(version, SortNodes(list), spellChecker);
}
private static Node[] SortNodes(List<Node> nodes)
......
......@@ -13,7 +13,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols
internal partial class SymbolTreeInfo : IObjectWritable
{
private const string PrefixMetadataSymbolTreeInfo = "<MetadataSymbolTreeInfoPersistence>_";
private const string SerializationFormat = "10";
private const string SerializationFormat = "9";
private static bool ShouldCreateFromScratch(
Solution solution,
......@@ -123,15 +123,7 @@ public void WriteTo(ObjectWriter writer)
writer.WriteInt32(node.ParentIndex);
}
if (_lazySpellChecker.IsValueCreated)
{
writer.WriteBoolean(true);
_lazySpellChecker.Value.WriteTo(writer);
}
else
{
writer.WriteBoolean(false);
}
_spellChecker.WriteTo(writer);
}
internal static SymbolTreeInfo ReadFrom(ObjectReader reader)
......@@ -149,7 +141,7 @@ internal static SymbolTreeInfo ReadFrom(ObjectReader reader)
var count = reader.ReadInt32();
if (count == 0)
{
return new SymbolTreeInfo(version, ImmutableArray<Node>.Empty);
return new SymbolTreeInfo(version, ImmutableArray<Node>.Empty, SpellChecker.Empty);
}
var nodes = new Node[count];
......@@ -161,10 +153,7 @@ internal static SymbolTreeInfo ReadFrom(ObjectReader reader)
nodes[i] = new Node(name, parentIndex);
}
var hasSpellChecker = reader.ReadBoolean();
return hasSpellChecker
? new SymbolTreeInfo(version, nodes, SpellChecker.ReadFrom(reader))
: new SymbolTreeInfo(version, nodes);
return new SymbolTreeInfo(version, nodes, SpellChecker.ReadFrom(reader));
}
catch (Exception)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册