private void AnalyzeInvokedMember( OperationAnalysisContext context, InfoCache infoCache, IOperation?instance, IMethodSymbol?targetMethod, IOperation argumentValue, IPropertySymbol?lengthLikeProperty, CancellationToken cancellationToken) { // look for `s[s.Length - value]` or `s.Get(s.Length- value)`. // Needs to have the one arg for `s.Length - value`, and that arg needs to be // a subtraction. if (instance is null || !IsSubtraction(argumentValue, out var subtraction)) { return; } if (subtraction.Syntax is not BinaryExpressionSyntax binaryExpression) { return; } // Don't bother analyzing if the user doesn't like using Index/Range operators. var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferIndexOperator, binaryExpression.SyntaxTree, cancellationToken); if (!option.Value) { return; } // Ok, looks promising. We're indexing in with some subtraction expression. Examine the // type this indexer is in to see if there's another member that takes a System.Index // that we can convert to. // // Also ensure that the left side of the subtraction : `s.Length - value` is actually // getting the length off the same instance we're indexing into. lengthLikeProperty ??= TryGetLengthLikeProperty(infoCache, targetMethod); if (lengthLikeProperty == null || !IsInstanceLengthCheck(lengthLikeProperty, instance, subtraction.LeftOperand)) { return; } if (CSharpSemanticFacts.Instance.IsInExpressionTree(instance.SemanticModel, instance.Syntax, infoCache.ExpressionOfTType, cancellationToken)) { return; } // Everything looks good. We can update this to use the System.Index member instead. context.ReportDiagnostic( DiagnosticHelper.Create( Descriptor, binaryExpression.GetLocation(), option.Notification.Severity, ImmutableArray <Location> .Empty, ImmutableDictionary <string, string?> .Empty)); }
protected override void InitializeWorker(AnalysisContext context) { context.RegisterCompilationStartAction(startContext => { // We're going to be checking every property-reference and invocation in the // compilation. Cache information we compute in this object so we don't have to // continually recompute it. var compilation = startContext.Compilation; var infoCache = new InfoCache(compilation); // Register to hear property references, so we can hear about calls to indexers // like: s[s.Length - n] context.RegisterOperationAction( c => AnalyzePropertyReference(c, infoCache), OperationKind.PropertyReference); // Register to hear about methods for: s.Get(s.Length - n) context.RegisterOperationAction( c => AnalyzeInvocation(c, infoCache), OperationKind.Invocation); var arrayType = compilation.GetSpecialType(SpecialType.System_Array); var arrayLengthProperty = TryGetNoArgInt32Property(arrayType, nameof(Array.Length)); if (arrayLengthProperty != null) { // Array indexing is represented with a different operation kind. Register // specifically for that. context.RegisterOperationAction( c => AnalyzeArrayElementReference(c, infoCache, arrayLengthProperty), OperationKind.ArrayElementReference); } }); }
public static Result?AnalyzeInvocation(IInvocationOperation invocation, InfoCache infoCache) { // Validate we're on a piece of syntax we expect. While not necessary for analysis, we // want to make sure we're on something the fixer will know how to actually fix. if (invocation.Syntax is not InvocationExpressionSyntax invocationSyntax || invocationSyntax.ArgumentList is null) { return(null); } // Check if we're at least on C# 8, and that the user wants these operators. var syntaxTree = invocationSyntax.SyntaxTree; var parseOptions = (CSharpParseOptions)syntaxTree.Options; if (parseOptions.LanguageVersion < LanguageVersion.CSharp8) { return(null); } // look for `s.Slice(e1, end - e2)` or `s.Slice(e1)` if (invocation.Instance is null) { return(null); } return(invocation.Arguments.Length switch { 1 => AnalyzeOneArgumentInvocation(invocation, infoCache, invocationSyntax), 2 => AnalyzeTwoArgumentInvocation(invocation, infoCache, invocationSyntax), _ => null, });
private void AnalyzePropertyReference(OperationAnalysisContext context, InfoCache infoCache) { var cancellationToken = context.CancellationToken; var propertyReference = (IPropertyReferenceOperation)context.Operation; // Only analyze indexer calls. if (!propertyReference.Property.IsIndexer) { return; } if (propertyReference.Arguments.Length != 1) { return; } AnalyzeInvokedMember( context, infoCache, propertyReference.Instance, propertyReference.Property.GetMethod, propertyReference.Arguments[0].Value, lengthLikePropertyOpt: null, cancellationToken ); }
private static SyntaxNode UpdateInvocation( SemanticModel semanticModel, SyntaxNode currentRoot, InvocationExpressionSyntax currentInvocation, SyntaxGenerator generator, CancellationToken cancellationToken) { if (semanticModel.GetOperation(currentInvocation, cancellationToken) is IInvocationOperation invocation) { var infoCache = new InfoCache(semanticModel.Compilation); var resultOpt = AnalyzeInvocation( invocation, infoCache, analyzerOptionsOpt: null, cancellationToken); if (resultOpt != null) { var result = resultOpt.Value; var updatedNode = FixOne(result, generator); if (updatedNode != null) { return(currentRoot.ReplaceNode(result.Invocation, updatedNode)); } } } return(currentRoot); }
private void AnalyzeArrayElementReference( OperationAnalysisContext context, InfoCache infoCache, IPropertySymbol arrayLengthProperty ) { var cancellationToken = context.CancellationToken; var arrayElementReference = (IArrayElementReferenceOperation)context.Operation; // Has to be a single-dimensional element access. if (arrayElementReference.Indices.Length != 1) { return; } AnalyzeInvokedMember( context, infoCache, arrayElementReference.ArrayReference, targetMethodOpt: null, arrayElementReference.Indices[0], lengthLikePropertyOpt: arrayLengthProperty, cancellationToken ); }
/// <summary> /// obtains the name of class /// </summary> /// <param name="template">templates name</param> /// <returns>returns a name of class</returns> private string GetNameType(string template) { List <Template> templates = new List <Template>(); InfoCache <List <Template> > cache = new InfoCache <List <Domain.Entities.Template> >(this.context) { TimeOut = 120 }; Domain.Entities.Template temp; TemplateRepository objtemplate = new TemplateRepository(this.session); templates = objtemplate.GetAll(); cache.SetCache("templates", templates); temp = templates.Find(t => t.TemplateId == template); if (temp != null) { return(temp.Nameclass); } else { return(null); } }
private void AnalyzeInvocation(OperationAnalysisContext context, InfoCache infoCache) { // Check if the user wants these operators. var option = context.GetCSharpAnalyzerOptions().PreferRangeOperator; if (!option.Value) { return; } var operation = context.Operation; var result = AnalyzeInvocation((IInvocationOperation)operation, infoCache); if (result == null) { return; } if (CSharpSemanticFacts.Instance.IsInExpressionTree(operation.SemanticModel, operation.Syntax, infoCache.ExpressionOfTType, context.CancellationToken)) { return; } context.ReportDiagnostic(CreateDiagnostic(result.Value, option.Notification.Severity)); }
private static IPropertySymbol TryGetLengthLikeProperty( InfoCache infoCache, IMethodSymbol targetMethodOpt ) => targetMethodOpt != null && infoCache.TryGetMemberInfo(targetMethodOpt, out var memberInfo) ? memberInfo.LengthLikeProperty : null;
public static Result?AnalyzeInvocation( IInvocationOperation invocation, InfoCache infoCache, AnalyzerOptions analyzerOptionsOpt, CancellationToken cancellationToken) { // Validate we're on a piece of syntax we expect. While not necessary for analysis, we // want to make sure we're on something the fixer will know how to actually fix. if (!(invocation.Syntax is InvocationExpressionSyntax invocationSyntax) || invocationSyntax.ArgumentList is null) { return(default);
protected override void InitializeWorker(AnalysisContext context) { context.RegisterCompilationStartAction(compilationContext => { // We're going to be checking every invocation in the compilation. Cache information // we compute in this object so we don't have to continually recompute it. var infoCache = new InfoCache(compilationContext.Compilation); compilationContext.RegisterOperationAction( c => AnalyzeInvocation(c, infoCache), OperationKind.Invocation); }); }
public AsyncStressClient() { running = true; sendCount = 0; recvCount = 0; recvErrorCount = 0; timeCost = 0; threads = new List <Thread>(); display = new InfoCache(); }
private void AnalyzeInvocation( OperationAnalysisContext context, InfoCache infoCache) { var resultOpt = AnalyzeInvocation( (IInvocationOperation)context.Operation, infoCache, context.Options, context.CancellationToken); if (resultOpt == null) { return; } context.ReportDiagnostic(CreateDiagnostic(resultOpt.Value)); }
public static Result?AnalyzeInvocation( IInvocationOperation invocation, InfoCache infoCache, AnalyzerOptions analyzerOptionsOpt, CancellationToken cancellationToken ) { // Validate we're on a piece of syntax we expect. While not necessary for analysis, we // want to make sure we're on something the fixer will know how to actually fix. if ( !(invocation.Syntax is InvocationExpressionSyntax invocationSyntax) || invocationSyntax.ArgumentList is null ) { return(null); } CodeStyleOption2 <bool> option = null; if (analyzerOptionsOpt != null) { // Check if we're at least on C# 8, and that the user wants these operators. var syntaxTree = invocationSyntax.SyntaxTree; var parseOptions = (CSharpParseOptions)syntaxTree.Options; if (parseOptions.LanguageVersion < LanguageVersion.CSharp8) { return(null); } option = analyzerOptionsOpt.GetOption( CSharpCodeStyleOptions.PreferRangeOperator, syntaxTree, cancellationToken ); if (!option.Value) { return(null); } } // look for `s.Slice(e1, end - e2)` or `s.Slice(e1)` if (invocation.Instance is null) { return(null); } return(invocation.Arguments.Length switch { 1 => AnalyzeOneArgumentInvocation(invocation, infoCache, invocationSyntax, option), 2 => AnalyzeTwoArgumentInvocation(invocation, infoCache, invocationSyntax, option), _ => null, });
public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out InfoCache?infoCache) { var indexType = compilation.GetBestTypeByMetadataName(typeof(Index).FullName !); if (indexType == null || !indexType.IsAccessibleWithin(compilation.Assembly)) { infoCache = null; return(false); } infoCache = new InfoCache(indexType, compilation.ExpressionOfTType()); return(true); }
public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out InfoCache?infoCache) { var rangeType = compilation.GetBestTypeByMetadataName(typeof(Range).FullName !); if (rangeType == null || !rangeType.IsAccessibleWithin(compilation.Assembly)) { infoCache = null; return(false); } var stringType = compilation.GetSpecialType(SpecialType.System_String); infoCache = new InfoCache(rangeType, stringType, compilation.ExpressionOfTType()); return(true); }
public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out InfoCache?infoCache) { var rangeType = compilation.GetBestTypeByMetadataName("System.Range"); if (rangeType == null) { infoCache = null; return(false); } var stringType = compilation.GetSpecialType(SpecialType.System_String); infoCache = new InfoCache(rangeType, stringType); return(true); }
protected override void InitializeWorker(AnalysisContext context) { context.RegisterCompilationStartAction(compilationContext => { // We're going to be checking every invocation in the compilation. Cache information // we compute in this object so we don't have to continually recompute it. var infoCache = new InfoCache(compilationContext.Compilation); // The System.Range type is always required to offer this fix. if (infoCache.RangeType != null) { compilationContext.RegisterOperationAction( c => AnalyzeInvocation(c, infoCache), OperationKind.Invocation); } }); }
/// <summary> /// Initializes a new instance of the <see cref="LanguageManagement"/> class /// </summary> /// <param name="session">framework that establishes communication between the application and the database</param> /// <param name="context">HTTP context</param> public LanguageManagement(ISession session, HttpContextBase context) { this.session = session; this.context = context; InfoCache <List <Language> > lang = new InfoCache <List <Language> >(context); this.colllang = lang.GetCache("languages"); if (this.colllang == null || this.colllang.Any().Equals(0)) { LanguageRepository langrepo = new LanguageRepository(session); this.colllang = langrepo.GetAll(); lang.SetCache("languages", this.colllang); } }
private void AnalyzeInvocation( OperationAnalysisContext context, InfoCache infoCache) { var cancellationToken = context.CancellationToken; var invocationOperation = (IInvocationOperation)context.Operation; if (invocationOperation.Arguments.Length != 1) { return; } AnalyzeInvokedMember( context, infoCache, invocationOperation.Instance, invocationOperation.TargetMethod, invocationOperation.Arguments[0].Value, lengthLikeProperty: null, cancellationToken); }
private static SyntaxNode UpdateInvocation( SemanticModel semanticModel, SyntaxNode currentRoot, InvocationExpressionSyntax currentInvocation, SyntaxGenerator generator, CancellationToken cancellationToken) { if (semanticModel.GetOperation(currentInvocation, cancellationToken) is IInvocationOperation invocation && InfoCache.TryCreate(semanticModel.Compilation, out var infoCache) && AnalyzeInvocation(invocation, infoCache) is { } result) { var updatedNode = FixOne(result, generator); if (updatedNode != null) { return(currentRoot.ReplaceNode(result.Invocation, updatedNode)); } } return(currentRoot); }
private void AnalyzeInvocation( OperationAnalysisContext context, InfoCache infoCache) { var syntaxTree = context.Operation.SemanticModel !.SyntaxTree; var cancellationToken = context.CancellationToken; var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferRangeOperator, syntaxTree, cancellationToken); if (!option.Value) { return; } var result = AnalyzeInvocation((IInvocationOperation)context.Operation, infoCache); if (result == null) { return; } context.ReportDiagnostic(CreateDiagnostic(result.Value, option.Notification.Severity)); }
public static Result?AnalyzeInvocation(IInvocationOperation invocation, InfoCache infoCache) { // Validate we're on a piece of syntax we expect. While not necessary for analysis, we // want to make sure we're on something the fixer will know how to actually fix. if (invocation.Syntax is not InvocationExpressionSyntax invocationSyntax || invocationSyntax.ArgumentList is null) { return(null); } // look for `s.Slice(e1, end - e2)` or `s.Slice(e1)` if (invocation.Instance is null) { return(null); } return(invocation.Arguments.Length switch { 1 => AnalyzeOneArgumentInvocation(invocation, infoCache, invocationSyntax), 2 => AnalyzeTwoArgumentInvocation(invocation, infoCache, invocationSyntax), _ => null, });
/// <summary> /// Initializes a new instance of the <see cref="FrontEndManagement"/> class /// </summary> /// <param name="session">framework that establishes communication between the application and the database</param> /// <param name="context">HTTP Context</param> /// <param name="type">Type of front end object</param> /// <param name="language">language of thread</param> public FrontEndManagement(ISession session, HttpContextBase context, Type type, Language language) { this.session = session; this.context = context; this.language = language; this.type = type; SectionRepository objsec = new SectionRepository(session); this.sections = new List <Section>(); InfoCache <List <Section> > cache = new InfoCache <List <Section> >(context) { TimeOut = 120 }; this.sections = cache.GetCache("sectionsactive"); if (this.sections == null) { objsec.Entity.Active = true; this.sections = objsec.GetAll(); cache.SetCache("sectionsactive", this.sections); } }
protected override void InitializeWorker(AnalysisContext context) { context.RegisterCompilationStartAction(context => { var compilation = (CSharpCompilation)context.Compilation; // Check if we're at least on C# 8 if (compilation.LanguageVersion < LanguageVersion.CSharp8) { return; } // We're going to be checking every invocation in the compilation. Cache information // we compute in this object so we don't have to continually recompute it. if (!InfoCache.TryCreate(context.Compilation, out var infoCache)) { return; } context.RegisterOperationAction( c => AnalyzeInvocation(c, infoCache), OperationKind.Invocation); }); }
/// <summary> /// inserts or updates a section object /// </summary> /// <param name="objSection">object section</param> /// <returns>returns true if operation successful</returns> public bool SaveSection(Section objSection) { try { SectionRepository sectionRepository = new SectionRepository(this.session); string section = objSection.Name; sectionRepository.Entity = objSection; if (sectionRepository.Entity.SectionId != null) { if (null != objSection.OldOrder && objSection.Sectionorder != null && objSection.Sectionorder != objSection.OldOrder) { sectionRepository.ChangeOrder(sectionRepository.Entity.Sectionorder.Value, objSection.OldOrder.Value); } sectionRepository.Update(); FriendlyurlRepository friendlyrepo = new FriendlyurlRepository(this.session); friendlyrepo.Entity.Id = sectionRepository.Entity.SectionId; friendlyrepo.Entity.Friendlyurlid = sectionRepository.Entity.Friendlyname; friendlyrepo.Entity.Type = Friendlyurl.FriendlyType.Section; friendlyrepo.Update(); InfoCache <List <Section> > cache = new InfoCache <List <Section> >(this.context) { TimeOut = 120 }; sectionRepository.Entity = new Section(); cache.SetCache("sections", sectionRepository.GetAll()); Utils.InsertAudit( this.session, new Audit() { Auditaction = "Update", Description = "Section -> " + section, Joindate = DateTime.Now, Username = (this.context.User as CustomPrincipal).UserId }); } else { sectionRepository.Entity.Sectionorder = sectionRepository.GetMaxOrder(); sectionRepository.Entity.Friendlyname = Utils.GetFindFrienlyName( this.session, sectionRepository.Entity.Name, sectionRepository.Entity.Sectionorder.Value); sectionRepository.Entity.SectionId = Convert.ToInt32(sectionRepository.Insert()); FriendlyurlRepository friendlyrepo = new FriendlyurlRepository(this.session); friendlyrepo.Entity.Id = sectionRepository.Entity.SectionId; friendlyrepo.Entity.Friendlyurlid = sectionRepository.Entity.Friendlyname; friendlyrepo.Entity.Type = Friendlyurl.FriendlyType.Section; friendlyrepo.Entity.LanguageId = sectionRepository.Entity.LanguageId; friendlyrepo.Insert(); Utils.InsertAudit( this.session, new Audit() { Auditaction = "Insert", Description = "Section -> " + section, Joindate = DateTime.Now, Username = (this.context.User as CustomPrincipal).UserId }); } return(true); } catch (Exception ex) { Utils.InsertLog( this.session, "Insert Section", ex.Message + " - " + ex.StackTrace); return(false); } }
private void AnalyzeInvokedMember( OperationAnalysisContext context, InfoCache infoCache, IOperation instance, IMethodSymbol targetMethodOpt, IOperation argumentValue, IPropertySymbol lengthLikePropertyOpt, CancellationToken cancellationToken) { // look for `s[s.Length - value]` or `s.Get(s.Length- value)`. // Needs to have the one arg for `s.Length - value`, and that arg needs to be // a subtraction. if (instance is null || !IsSubtraction(argumentValue, out var subtraction)) { return; } if (!(subtraction.Syntax is BinaryExpressionSyntax binaryExpression)) { return; } // Only supported on C# 8 and above. var syntaxTree = binaryExpression.SyntaxTree; var parseOptions = (CSharpParseOptions)syntaxTree.Options; if (parseOptions.LanguageVersion < LanguageVersion.CSharp8) { return; } // Don't bother analyzing if the user doesn't like using Index/Range operators. var optionSet = context.Options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet is null) { return; } var option = optionSet.GetOption(CSharpCodeStyleOptions.PreferIndexOperator); if (!option.Value) { return; } // Ok, looks promising. We're indexing in with some subtraction expression. Examine the // type this indexer is in to see if there's another member that takes a System.Index // that we can convert to. // // Also ensure that the left side of the subtraction : `s.Length - value` is actually // getting the length off the same instance we're indexing into. lengthLikePropertyOpt = lengthLikePropertyOpt ?? TryGetLengthLikeProperty(infoCache, targetMethodOpt); if (lengthLikePropertyOpt == null || !IsInstanceLengthCheck(lengthLikePropertyOpt, instance, subtraction.LeftOperand)) { return; } // Everything looks good. We can update this to use the System.Index member instead. context.ReportDiagnostic( DiagnosticHelper.Create( Descriptor, binaryExpression.GetLocation(), option.Notification.Severity, ImmutableArray <Location> .Empty, ImmutableDictionary <string, string> .Empty)); }
private async Task LogAllReliableCollections() { while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } StringBuilder sb = new StringBuilder(); sb.AppendLine("Reliable Collections"); sb.AppendLine("CurrentGidToPointItemMap =>"); var currentGidToPointItemMap = await CurrentGidToPointItemMap.GetEnumerableDictionaryAsync(); foreach (var element in currentGidToPointItemMap) { sb.AppendLine($"Key => {element.Key}, Value => Gid: 0x{element.Value.Gid:X16}, Address: {element.Value.Address}, Name: {element.Value.Name}, RegisterType: {element.Value.RegisterType}, Alarm: {element.Value.Alarm}, Initialized: {element.Value.Initialized}"); } sb.AppendLine(); sb.AppendLine("IncomingGidToPointItemMap =>"); var incomingGidToPointItemMap = await IncomingGidToPointItemMap.GetEnumerableDictionaryAsync(); foreach (var element in incomingGidToPointItemMap) { sb.AppendLine($"Key => {element.Key}, Value => Gid: 0x{element.Value.Gid:X16}, Address: {element.Value.Address}, Name: {element.Value.Name}, RegisterType: {element.Value.RegisterType}, Alarm: {element.Value.Alarm}, Initialized: {element.Value.Initialized}"); } sb.AppendLine(); sb.AppendLine("CurrentAddressToGidMap =>"); var currentAddressToGidMap = await CurrentAddressToGidMap.GetEnumerableDictionaryAsync(); foreach (var element in currentAddressToGidMap) { sb.AppendLine($"Key => {element.Key}, Value => Dictionary Count: {element.Value.Count}"); } sb.AppendLine(); sb.AppendLine("IncomingAddressToGidMap =>"); var incomingAddressToGidMap = await IncomingAddressToGidMap.GetEnumerableDictionaryAsync(); foreach (var element in incomingAddressToGidMap) { sb.AppendLine($"Key => {element.Key}, Value => Dictionary Count: {element.Value.Count}"); } sb.AppendLine(); sb.AppendLine("InfoCache =>"); var infoCache = await InfoCache.GetEnumerableDictionaryAsync(); foreach (var element in infoCache) { sb.AppendLine($"Key => {element.Key}, Value => {element.Value}"); } sb.AppendLine(); sb.AppendLine("ModelChanges =>"); var modelChanges = await ModelChanges.GetEnumerableDictionaryAsync(); foreach (var element in modelChanges) { sb.AppendLine($"Key => {element.Key}, Value => List Count: {element.Value.Count}"); } sb.AppendLine(); sb.AppendLine("MeasurementsCache =>"); var measurementsCache = await MeasurementsCache.GetEnumerableDictionaryAsync(); foreach (var element in measurementsCache) { sb.AppendLine($"Key => {element.Key}, Value => MeasurementGid: {element.Value.MeasurementGid:X16}, Alarm: {element.Value.Alarm}, CommandOrigin: {element.Value.CommandOrigin}"); } sb.AppendLine(); sb.AppendLine("CommandDescriptionCache =>"); var commandDescriptionCache = await CommandDescriptionCache.GetEnumerableDictionaryAsync(); foreach (var element in commandDescriptionCache) { sb.AppendLine($"Key => {element.Key}, Value => Gid: {element.Value.Gid:X16}, Address: {element.Value.Address}, Value: {element.Value.Value}, CommandOrigin: {element.Value.CommandOrigin}"); } sb.AppendLine(); Logger.LogDebug($"{baseLogString} LogAllReliableCollections => {sb}"); }
public static Result?AnalyzeInvocation( IInvocationOperation invocation, InfoCache infoCache, AnalyzerOptions analyzerOptionsOpt, CancellationToken cancellationToken) { // Validate we're on a piece of syntax we expect. While not necessary for analysis, we // want to make sure we're on something the fixer will know how to actually fix. if (!(invocation.Syntax is InvocationExpressionSyntax invocationSyntax) || invocationSyntax.ArgumentList is null) { return(null); } CodeStyleOption <bool> option = null; if (analyzerOptionsOpt != null) { // Check if we're at least on C# 8, and that the user wants these operators. var syntaxTree = invocationSyntax.SyntaxTree; var parseOptions = (CSharpParseOptions)syntaxTree.Options; if (parseOptions.LanguageVersion < LanguageVersion.CSharp8) { return(null); } option = analyzerOptionsOpt.GetOption(CSharpCodeStyleOptions.PreferRangeOperator, syntaxTree, cancellationToken); if (!option.Value) { return(null); } } // look for `s.Slice(e1, end - e2)` if (invocation.Instance is null || invocation.Arguments.Length != 2) { return(null); } // See if the call is to something slice-like. var targetMethod = invocation.TargetMethod; // Second arg needs to be a subtraction for: `end - e2`. Once we've seen that we have // that, try to see if we're calling into some sort of Slice method with a matching // indexer or overload if (!IsSubtraction(invocation.Arguments[1].Value, out var subtraction) || !infoCache.TryGetMemberInfo(targetMethod, out var memberInfo)) { return(null); } // See if we have: (start, end - start). Specifically where the start operation it the // same as the right side of the subtraction. var startOperation = invocation.Arguments[0].Value; if (CSharpSyntaxFacts.Instance.AreEquivalent(startOperation.Syntax, subtraction.RightOperand.Syntax)) { return(new Result( ResultKind.Computed, option, invocation, invocationSyntax, targetMethod, memberInfo, startOperation, subtraction.LeftOperand)); } // See if we have: (constant1, s.Length - constant2). The constants don't have to be // the same value. This will convert over to s[constant1..(constant - constant1)] if (IsConstantInt32(startOperation) && IsConstantInt32(subtraction.RightOperand) && IsInstanceLengthCheck(memberInfo.LengthLikeProperty, invocation.Instance, subtraction.LeftOperand)) { return(new Result( ResultKind.Constant, option, invocation, invocationSyntax, targetMethod, memberInfo, startOperation, subtraction.RightOperand)); } return(null); }