public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationContext => { var formatInfo = new StringFormatInfo(compilationContext.Compilation); compilationContext.RegisterOperationAction(operationContext => { var invocation = (IInvocationOperation)operationContext.Operation; StringFormatInfo.Info info = formatInfo.TryGet(invocation.TargetMethod, operationContext); if (info == null || invocation.Arguments.Length <= info.FormatStringIndex) { // not a target method return; } IArgumentOperation formatStringArgument = invocation.Arguments[info.FormatStringIndex]; if (!object.Equals(formatStringArgument?.Value?.Type, formatInfo.String) || !(formatStringArgument?.Value?.ConstantValue.Value is string)) { // wrong argument return; } var stringFormat = (string)formatStringArgument.Value.ConstantValue.Value; int expectedStringFormatArgumentCount = GetFormattingArguments(stringFormat); // explict parameter case if (info.ExpectedStringFormatArgumentCount >= 0) { // __arglist is not supported here if (invocation.TargetMethod.IsVararg) { // can't deal with this for now. return; } if (info.ExpectedStringFormatArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } return; } // ensure argument is an array IArgumentOperation paramsArgument = invocation.Arguments[info.FormatStringIndex + 1]; if (paramsArgument.ArgumentKind != ArgumentKind.ParamArray && paramsArgument.ArgumentKind != ArgumentKind.Explicit) { // wrong format return; } var arrayCreation = paramsArgument.Value as IArrayCreationOperation; var elementType = arrayCreation.GetElementType(); if (elementType == null || !object.Equals(elementType, formatInfo.Object) || arrayCreation.DimensionSizes.Length != 1) { // wrong format return; } // compiler generating object array for params case IArrayInitializerOperation intializer = arrayCreation.Initializer; if (intializer == null) { // unsupported format return; } // REVIEW: "ElementValues" is a bit confusing where I need to double dot those to get number of elements int actualArgumentCount = intializer.ElementValues.Length; if (actualArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } }, OperationKind.Invocation); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.RegisterCompilationStartAction(compilationContext => { var formatInfo = new StringFormatInfo(compilationContext.Compilation); compilationContext.RegisterOperationAction(operationContext => { var invocation = (IInvocationExpression)operationContext.Operation; StringFormatInfo.Info info = formatInfo.TryGet(invocation.TargetMethod); if (info == null || invocation.ArgumentsInParameterOrder.Length <= info.FormatStringIndex) { // not a target method return; } IArgument formatStringArgument = invocation.ArgumentsInParameterOrder[info.FormatStringIndex]; if (!object.Equals(formatStringArgument?.Value?.Type, formatInfo.String) || !(formatStringArgument?.Value?.ConstantValue.Value is string)) { // wrong argument return; } var stringFormat = (string)formatStringArgument.Value.ConstantValue.Value; int expectedStringFormatArgumentCount = GetFormattingArguments(stringFormat); // explict parameter case if (info.ExpectedStringFormatArgumentCount >= 0) { // TODO: due to a bug - https://github.com/dotnet/roslyn/issues/7346 // vararg case is disabled. // we might check this only for C# since __arglist is not supported in VB // // we need to implement proper support for __arglist once the bug is fixed. if (invocation.TargetMethod.IsVararg) { // can't deal with this for now. return; } if (info.ExpectedStringFormatArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } return; } // params case IArgument paramsArgument = invocation.ArgumentsInParameterOrder[info.FormatStringIndex + 1]; if (paramsArgument.ArgumentKind != ArgumentKind.ParamArray) { // wrong format return; } var arrayCreation = paramsArgument.Value as IArrayCreationExpression; if (arrayCreation == null || !object.Equals(arrayCreation.ElementType, formatInfo.Object) || arrayCreation.DimensionSizes.Length != 1) { // wrong format return; } // compiler generating object array for params case IArrayInitializer intializer = arrayCreation.Initializer; if (intializer == null) { // unsupported format return; } // REVIEW: "ElementValues" is a bit confusing where I need to double dot those to get number of elements int actualArgumentCount = intializer.ElementValues.Length; if (actualArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } }, OperationKind.InvocationExpression); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction(compilationContext => { var formatInfo = new StringFormatInfo(compilationContext.Compilation); compilationContext.RegisterOperationAction(operationContext => { var invocation = (IInvocationExpression)operationContext.Operation; StringFormatInfo.Info info = formatInfo.TryGet(invocation.TargetMethod); if (info == null || invocation.ArgumentsInParameterOrder.Length <= info.FormatStringIndex) { // not a target method return; } IArgument formatStringArgument = invocation.ArgumentsInParameterOrder[info.FormatStringIndex]; if (!object.Equals(formatStringArgument?.Value?.Type, formatInfo.String) || !(formatStringArgument?.Value?.ConstantValue.Value is string)) { // wrong argument return; } var stringFormat = (string)formatStringArgument.Value.ConstantValue.Value; int expectedStringFormatArgumentCount = GetFormattingArguments(stringFormat); // explict parameter case if (info.ExpectedStringFormatArgumentCount >= 0) { // __arglist is not supported here if (invocation.TargetMethod.IsVararg) { // can't deal with this for now. return; } if (info.ExpectedStringFormatArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } return; } // params case IArgument paramsArgument = invocation.ArgumentsInParameterOrder[info.FormatStringIndex + 1]; if (paramsArgument.ArgumentKind != ArgumentKind.ParamArray) { // wrong format return; } var arrayCreation = paramsArgument.Value as IArrayCreationExpression; if (arrayCreation == null || !object.Equals(arrayCreation.ElementType, formatInfo.Object) || arrayCreation.DimensionSizes.Length != 1) { // wrong format return; } // compiler generating object array for params case IArrayInitializer intializer = arrayCreation.Initializer; if (intializer == null) { // unsupported format return; } // REVIEW: "ElementValues" is a bit confusing where I need to double dot those to get number of elements int actualArgumentCount = intializer.ElementValues.Length; if (actualArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } }, OperationKind.InvocationExpression); }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.RegisterCompilationStartAction(compilationContext => { var formatInfo = new StringFormatInfo(compilationContext.Compilation); compilationContext.RegisterOperationAction(operationContext => { var invocation = (IInvocationExpression)operationContext.Operation; var info = formatInfo.TryGet(invocation.TargetMethod); if (info == null || invocation.ArgumentsInParameterOrder.Length <= info.FormatStringIndex) { // not a target method return; } var formatStringArgument = invocation.ArgumentsInParameterOrder[info.FormatStringIndex]; if (!object.Equals(formatStringArgument?.Value?.ResultType, formatInfo.String) || !(formatStringArgument?.Value?.ConstantValue.Value is string)) { // wrong argument return; } var stringFormat = (string)formatStringArgument.Value.ConstantValue.Value; var expectedStringFormatArgumentCount = GetFormattingArguments(stringFormat); // explict parameter case if (info.ExpectedStringFormatArgumentCount >= 0) { // TODO: due to a bug - https://github.com/dotnet/roslyn/issues/7346 // vararg case is disabled. // we might check this only for C# since __arglist is not supported in VB // // we need to implement proper support for __arglist once the bug is fixed. if (invocation.TargetMethod.IsVararg) { // can't deal with this for now. return; } if (info.ExpectedStringFormatArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } return; } // params case var paramsArgument = invocation.ArgumentsInParameterOrder[info.FormatStringIndex + 1]; if (paramsArgument.ArgumentKind != ArgumentKind.ParamArray) { // wrong format return; } var arrayCreation = paramsArgument.Value as IArrayCreationExpression; if (arrayCreation == null || !object.Equals(arrayCreation.ElementType, formatInfo.Object) || arrayCreation.DimensionSizes.Length != 1) { // wrong format return; } // compiler generating object array for params case var intializer = arrayCreation.Initializer; if (intializer == null) { // unsupported format return; } // REVIEW: "ElementValues" is a bit confusing where I need to double dot those to get number of elements var actualArgumentCount = intializer.ElementValues.Length; if (actualArgumentCount != expectedStringFormatArgumentCount) { operationContext.ReportDiagnostic(operationContext.Operation.Syntax.CreateDiagnostic(Rule)); } }, OperationKind.InvocationExpression); }); }