public override void VisitInvocationExpression(IInvocationExpression invocation, IHighlightingConsumer consumer) { if (IsCallWithTheSameContextAsFunctionOwner(invocation)) consumer.AddHighlighting(new CallWithSameContextWarning(invocation), invocation.GetHighlightingRange(), File); base.VisitInvocationExpression(invocation, consumer); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) { var element = referenceExpression.Reference.Resolve().DeclaredElement; var typeOwner = element as ITypeOwner; if (typeOwner == null) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } var modifiersOwner = element as IModifiersOwner; if (modifiersOwner == null) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } if (!IsManaged(modifiersOwner)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } //virtual and abstract cannot be in struct. only override is getHashCode -> function consumer?.AddHighlighting(new BurstLoadingManagedTypeWarning(referenceExpression, typeOwner.Type().GetTypeElement()?.ShortName + "." + element.ShortName)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IInvocationExpression invocationExpression, IHighlightingConsumer consumer) { var invokedMethod = invocationExpression.Reference.Resolve().DeclaredElement as IMethod; if (invokedMethod == null) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } if (!IsDebugLog(invokedMethod)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } var argumentList = invocationExpression.ArgumentList.Arguments; if (argumentList.Count != 1) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } var argument = argumentList[0]; if (argument == null || IsBurstPossibleArgumentString(argument)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } consumer?.AddHighlighting(new BurstDebugLogInvalidArgumentWarning(argument.Expression)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
public bool CheckAndAnalyze(ICSharpExpression startNode, IHighlighting highlighting, IHighlightingConsumer consumer) { ITreeNode currentNode = startNode; var result = false; var analyzed = false; while (!analyzed && currentNode is ICSharpExpression cSharpExpression) { foreach (var subAnalyzer in mySubAnalyzers) { analyzed = subAnalyzer.TryAnalyze(cSharpExpression, out result); if (analyzed) { break; } } currentNode = currentNode.Parent; } if (!analyzed || result) { result = true; consumer?.AddHighlighting(highlighting); } return(result); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IInvocationExpression invocationExpression, IHighlightingConsumer consumer) { var invokedMethod = invocationExpression.Reference.Resolve().DeclaredElement as IMethod; if (!BurstCodeAnalysisUtil.IsSharedStaticCreateMethod(invokedMethod)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } if (invokedMethod.TypeParameters.Count != 0) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } var methodParameters = invokedMethod.Parameters; for (var index = 0; index < methodParameters.Count - 1; index++) { if (!methodParameters[index].Type.IsSystemType()) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } } consumer?.AddHighlighting(new BurstSharedStaticCreateWarning(invocationExpression)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) { var element = referenceExpression.Reference.Resolve().DeclaredElement; if (!(element is ITypeOwner typeOwner)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } if (typeOwner is IAttributesOwner attributesOwner && attributesOwner.HasAttributeInstance(KnownTypes.NativeSetClassTypeToNullOnScheduleAttribute, AttributesSource.Self)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } if (BurstCodeAnalysisUtil.IsBurstPermittedType(typeOwner.Type())) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } consumer?.AddHighlighting(new BurstLoadingManagedTypeWarning( referenceExpression, typeOwner.Type().GetTypeElement()?.ShortName)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) { var element = referenceExpression.Reference.Resolve().DeclaredElement; //non auto property are not interested cuz they are not prohibited, //and any backing field will be handled inside accessor if ((!(element is IProperty property) || !property.IsAuto) && !(element is IField)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } var typeMember = (ITypeMember)element; if (!referenceExpression.GetAccessType().HasFlag(ExpressionAccessType.Read) || !typeMember.IsStatic || typeMember.IsReadonly || typeMember.IsConstant() || typeMember.IsEnumMember() || typeMember is IProperty prop && !prop.IsWritable && prop.IsReadable) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } consumer?.AddHighlighting(new BurstLoadingStaticNotReadonlyWarning(referenceExpression, typeMember.GetContainingType()?.ShortName + "." + element.ShortName)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) { var element = referenceExpression.Reference.Resolve().DeclaredElement; //non auto property are not interested cuz they are not prohibited, //and any backing field will be handled inside accessor if ((!(element is IProperty property) || !property.IsAuto) && !(element is IField)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } var typeMember = (ITypeMember)element; if (!referenceExpression.GetAccessType().HasFlag(ExpressionAccessType.Write) || !typeMember.IsStatic) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } //there are no static write-only auto properties consumer?.AddHighlighting(new BurstWriteStaticFieldWarning(referenceExpression, element.ShortName)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
protected override void Run(IDllImportMethodDeclaration importMethod, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { var element = importMethod.MethodDeclaration; var libraryName = importMethod.ImportedDll; var factory = new LibraryFactory(); var library = factory.LoadLibrary(libraryName); var export = library[element.NameIdentifier.Name]; if (export == null || export.Parameters.Count != element.ParameterDeclarations.Count) { return; } for (var i = 0; i < element.ParameterDeclarations.Count; i++ ) { var parameter = element.ParameterDeclarations[i]; var knownParameter = export.Parameters[i]; var exportedType = new ClrTypeName(knownParameter.CLRType.FullName); if (parameter.Type.IsInt() && exportedType.Equals(IntPtrClrType)) { consumer.AddHighlighting(new DllImportInt32ForIntPtrHighlighting(parameter)); } var marshalAs = parameter.Attributes.GetAttibuteOfCLRType(MarshalAsAttribute); if (knownParameter.UnmanagedType.HasValue && marshalAs != null && marshalAs.ConstructorArgumentExpressions.Count == 1) { var argumentExpression = marshalAs.ConstructorArgumentExpressions[0]; if (!argumentExpression.IsConstantValue()) { continue; } var shortType = argumentExpression.ConstantValue.IsShort(); UnmanagedType unmanagedType; if (shortType) { unmanagedType = (UnmanagedType)(short)argumentExpression.ConstantValue.Value; } else { unmanagedType = (UnmanagedType)argumentExpression.ConstantValue.Value; } if (knownParameter.UnmanagedType.Value != unmanagedType) { consumer.AddHighlighting(new DllImportIncorrectParameterMarshalHighlighting(parameter, argumentExpression, knownParameter.UnmanagedType.Value)); } } } }
public override void VisitNode(ITreeNode element, IHighlightingConsumer consumer) { var tokenNode = element as ITokenNode; if (tokenNode != null && tokenNode.GetTokenType().IsWhitespace) return; var colorInfo = CreateColorHighlightingInfo(element); if (colorInfo != null) consumer.AddHighlighting(colorInfo.Highlighting, colorInfo.Range); }
protected override bool CheckAndAnalyze(IObjectCreationExpression objectCreationExpression, IHighlightingConsumer consumer) { if (!IsBurstPermittedType(objectCreationExpression.Type())) { consumer?.AddHighlighting(new BurstCreatingManagedTypeWarning(objectCreationExpression.GetDocumentRange(), (objectCreationExpression.ConstructorReference.Resolve().DeclaredElement as IConstructor)?.GetContainingType()?.ShortName)); return(true); } return(false); }
private void AddHighLighting( DocumentRange range, ITreeNode element, IHighlightingConsumer consumer, IHighlighting highlighting) { var info = new HighlightingInfo(range, highlighting, new Severity?()); IFile file = element.GetContainingFile(); if (file != null) { consumer.AddHighlighting(info.Highlighting, file); } }
public override void VisitRuleDeclaredName(IRuleDeclaredName ruleDeclaredName, IHighlightingConsumer consumer) { string name = ruleDeclaredName.GetText(); if (myDeclarations.ContainsKey(name)) { List<IDeclaration> list = myDeclarations.GetValue(name); if (list.Count > 1) { consumer.AddHighlighting(new DuplicatingLocalDeclarationError(ruleDeclaredName), File); } } base.VisitRuleDeclaredName(ruleDeclaredName, consumer); }
public override void VisitRuleDeclaration(IRuleDeclaration ruleDeclaration, IHighlightingConsumer consumer) { IRuleBody body = ruleDeclaration.Body; ITreeNode child = PsiTreeUtil.GetFirstChild<IRuleName>(body); var ruleName = child as IRuleName; if (ruleName != null) { if (ruleName.GetText().Equals(ruleDeclaration.DeclaredName)) { consumer.AddHighlighting(new LeftRecursionWarning(ruleName), File); } } base.VisitRuleDeclaration(ruleDeclaration, consumer); }
private void VisitLoop(ITreeNode loop, IHighlightingConsumer consumer) { var function = loop.GetContainingNode<IJsFunctionLike>(); var accessAnalizer = new VariableCollector(); loop.ProcessThisAndDescendants(accessAnalizer); var accessToExternalModifiedClosure = accessAnalizer.Variables .GroupBy(r => r.DeclaredElement) .Select(g => g.ToArray()) .Where(l => HasExternallyModifiedClosure(function, l)) .SelectMany(l => l) .Where(r => r.FunctionLike != function) .Select(info => info.Node); foreach (var expression in accessToExternalModifiedClosure) { consumer.AddHighlighting(new AccessToModifiedClosureWarning(expression), expression.GetHighlightingRange(), File); } }
public override void VisitClassDeclaration(IClassDeclaration classDeclarationParam, IHighlightingConsumer context) { base.VisitClassDeclaration(classDeclarationParam, context); if (!classDeclarationParam.IsSynthetic() || !T4CSharpCodeGenerator.ClassName.Equals(classDeclarationParam.DeclaredName, StringComparison.Ordinal)) return; IDeclaredTypeUsage superTypeUsage = classDeclarationParam.SuperTypeUsageNodes.FirstOrDefault(); if (superTypeUsage == null || T4CSharpCodeGenerator.DefaultBaseClassName.Equals(superTypeUsage.GetText(), StringComparison.Ordinal)) return; ITypeElement typeElement = CSharpTypeFactory.CreateDeclaredType(superTypeUsage).GetTypeElement(); if (typeElement == null) return; if (!typeElement.Methods.Any(IsTransformTextMethod)) context.AddHighlighting(new MissingTransformTextMethodHighlighting(superTypeUsage)); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IInvocationExpression invocationExpression, IHighlightingConsumer consumer) { var invokedMethod = invocationExpression.Reference.Resolve().DeclaredElement as IMethod; if (invokedMethod == null) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } if (!IsStringFormat(invokedMethod)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } var argumentList = invocationExpression.ArgumentList.Arguments; var isWarningPlaced = BurstStringLiteralOwnerAnalyzer.CheckAndAnalyze(invocationExpression, new BurstManagedStringWarning(invocationExpression), consumer); if (isWarningPlaced) { return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); } if (argumentList.Count == 0) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } var firstArgument = argumentList[0]; var cSharpLiteralExpression = firstArgument.Expression as ICSharpLiteralExpression; if (cSharpLiteralExpression != null && cSharpLiteralExpression.Literal.GetTokenType().IsStringLiteral) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } consumer?.AddHighlighting( new BurstDebugLogInvalidArgumentWarning(firstArgument.Expression)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IInvocationExpression invocationExpression, IHighlightingConsumer consumer) { var invokedMethod = invocationExpression.Reference.Resolve().DeclaredElement as IMethod; if (invokedMethod == null || UnityCallGraphUtil.IsQualifierOpenType(invocationExpression)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } if (!IsBurstProhibitedObjectMethod(invokedMethod)) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); } consumer?.AddHighlighting(new BurstAccessingManagedMethodWarning(invocationExpression, invokedMethod.ShortName, invokedMethod.GetContainingType()?.ShortName)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); }
public BurstProblemSubAnalyzerStatus CheckAndAnalyze(IInvocationExpression invocationExpression, IHighlightingConsumer consumer) { var invokedMethod = invocationExpression.Reference.Resolve().DeclaredElement as IParametersOwner; if (invokedMethod == null) { return(BurstProblemSubAnalyzerStatus.NO_WARNING_STOP); } var argumentList = invocationExpression.ArgumentList; if (HasBurstProhibitedReturnValue(invokedMethod) || argumentList != null && HasBurstProhibitedArguments(invocationExpression.ArgumentList)) { consumer?.AddHighlighting( new BurstFunctionSignatureContainsManagedTypesWarning(invocationExpression, invokedMethod.ShortName)); return(BurstProblemSubAnalyzerStatus.WARNING_PLACED_STOP); } return(BurstProblemSubAnalyzerStatus.NO_WARNING_CONTINUE); }
public override void VisitNode(ITreeNode node, IHighlightingConsumer context) { base.VisitNode(node, context); string attributeId = GetHighlightingAttributeId(node); if (attributeId != null) context.AddHighlighting(new PredefinedHighlighting(attributeId), node.GetHighlightingRange()); }
private static void CheckForeachDeclaration( [NotNull] IForeachStatement foreachStatement, [NotNull] IHighlightingConsumer consumer) { var collection = foreachStatement.Collection; if (collection == null) { return; } var collectionType = collection.Type() as IDeclaredType; if (collectionType == null || collectionType.IsUnknown) { return; } // no allocations because of compiler support (just like arrays) if (collectionType.IsString()) { return; } var typeElement = collectionType.GetTypeElement(); if (typeElement == null) { return; } // search for GetEnumerator() method var symbolTable = ResolveUtil.GetSymbolTableByTypeElement( typeElement, SymbolTableMode.FULL, typeElement.Module); foreach (var symbolInfo in symbolTable.GetSymbolInfos("GetEnumerator")) { var method = symbolInfo.GetDeclaredElement() as IMethod; if (method == null) { continue; } if (!CSharpDeclaredElementUtil.IsForeachEnumeratorPatternMember(method)) { continue; } // with ref-return if (method.ReturnType.Classify == TypeClassification.REFERENCE_TYPE) { DocumentRange range; var inToken = collection.GetPreviousMeaningfulToken(); if (inToken != null && inToken.GetTokenType().IsKeyword) { range = inToken.GetDocumentRange(); } else { range = collection.GetExpressionRange(); } consumer.AddHighlighting( new ObjectAllocationHighlighting(foreachStatement, "possible enumerator allocation (except iterators or collection with cached enumerator)"), range); } break; } }
void AnalyzeWhenExpressionIsKnownToBeNullOrNotNull( [NotNull] IHighlightingConsumer context, [CanBeNull] CSharpCompilerNullableInspector nullabilityInspector, [CanBeNull] CSharpControlFlowGraphInspector inspector, [CanBeNull][ItemNotNull] HashSet <IAsExpression> alwaysSuccessTryCastExpressions, [NotNull] Assertion assertion, bool isKnownToBeNull) { if (assertion is AssertionStatement assertionStatement) { // pattern: Assert(null); Debug.Assert(CSharpTokenType.NULL_KEYWORD != null); if (isKnownToBeNull && IsLiteral(assertionStatement.Expression, CSharpTokenType.NULL_KEYWORD)) { context.AddHighlighting( new RedundantAssertionStatementSuggestion("Assertion is redundant because the expression is null here.", assertionStatement)); } // pattern: Assert(x); when x is known to be null or not null switch (GetExpressionNullReferenceState( nullabilityInspector, inspector, alwaysSuccessTryCastExpressions, assertionStatement.Expression)) { case CSharpControlFlowNullReferenceState.NOT_NULL: if (!isKnownToBeNull) { context.AddHighlighting( new RedundantAssertionStatementSuggestion( "Assertion is redundant because the expression is not null here.", assertionStatement)); } break; case CSharpControlFlowNullReferenceState.NULL: if (isKnownToBeNull) { context.AddHighlighting( new RedundantAssertionStatementSuggestion( "Assertion is redundant because the expression is null here.", assertionStatement)); } break; } } if (!isKnownToBeNull) { switch (assertion) { case InlineAssertion inlineAssertion: if (GetExpressionNullReferenceState( nullabilityInspector, inspector, alwaysSuccessTryCastExpressions, inlineAssertion.QualifierExpression) == CSharpControlFlowNullReferenceState.NOT_NULL) { context.AddHighlighting( new RedundantInlineAssertionSuggestion( "Assertion is redundant because the expression is not null here.", inlineAssertion)); } break; case NullForgivingOperation nullForgivingOperation: Debug.Assert(nullForgivingOperation.SuppressNullableWarningExpression.Operand != null); if (GetExpressionNullReferenceState( nullabilityInspector, inspector, alwaysSuccessTryCastExpressions, nullForgivingOperation.SuppressNullableWarningExpression.Operand) == CSharpControlFlowNullReferenceState.NOT_NULL) { context.AddHighlighting( new RedundantNullForgivingOperatorSuggestion( "Null-forgiving operator is redundant because the expression is not null here.", nullForgivingOperation)); } break; } } }
private void AddSentenceSuggestionHighlighting( IHighlightingConsumer consumer, string message, ISentence startElement, ISentence endElement) { var highlighting = new HintRangeHighlighting<ISentence>(startElement, endElement, message); IFile file = startElement.GetContainingFile(); if (file != null) { consumer.AddHighlighting(highlighting, file); } }
protected override bool CheckAndAnalyze(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) { var element = referenceExpression.Reference.Resolve().DeclaredElement; //here I want to handle next situations //1. accessing type members, whether static or not, including: properties, fields, localVariable, parameters //non auto property are not interested cuz they are not prohibited, //and any backing field will be handled inside accessor if (element is IProperty property && property.IsAuto || element is IField) { var typeMember = (ITypeMember)element; if (referenceExpression.GetAccessType().HasFlag(ExpressionAccessType.Read) && typeMember.IsStatic && !typeMember.IsReadonly && !typeMember.IsConstant() && !typeMember.IsEnumMember() && !(typeMember is IProperty prop && !prop.IsWritable && prop.IsReadable)) { consumer?.AddHighlighting(new BurstLoadingStaticNotReadonlyWarning( referenceExpression.GetDocumentRange(), typeMember.GetContainingType()?.ShortName + "." + element.ShortName)); return(true); } if (referenceExpression.GetAccessType().HasFlag(ExpressionAccessType.Write) && typeMember.IsStatic) { //there are no static write-only auto properties var field = element.ShortName; if (element is IProperty) { field += "__backing_field"; } consumer?.AddHighlighting(new BurstWriteStaticFieldWarning(referenceExpression.GetDocumentRange(), field)); return(true); } } if (element is ITypeOwner typeOwner) { if (element is IModifiersOwner modifiersOwner && (modifiersOwner.IsVirtual || modifiersOwner.IsOverride || modifiersOwner.IsAbstract)) { //virtual and abstract cannot be in struct. only override is getHashCode -> function consumer?.AddHighlighting(new BurstLoadingManagedTypeWarning( referenceExpression.GetDocumentRange(), typeOwner.Type().GetTypeElement()?.ShortName + "." + element.ShortName)); return(true); } if (!IsBurstPermittedType(typeOwner.Type())) { if (typeOwner is IAttributesOwner attributesOwner && attributesOwner.HasAttributeInstance(KnownTypes.NativeSetClassTypeToNullOnScheduleAttribute, AttributesSource.Self)) { return(false); } consumer?.AddHighlighting(new BurstLoadingManagedTypeWarning( referenceExpression.GetDocumentRange(), typeOwner.Type().GetTypeElement()?.ShortName)); return(true); } } return(false); }
private void AddHighLighting(DocumentRange range, IHighlightingConsumer consumer, IHighlighting highlighting) { var info = new HighlightingInfo(range, highlighting, new Severity?()); consumer.AddHighlighting(info.Highlighting, file); }
public static void SpellCheck( IDocument document, ITokenNode token, ISpellChecker spellChecker, ISolution solution, IHighlightingConsumer highlightingConsumer, IContextBoundSettingsStore settingsStore, CommentSettings settings) { if (spellChecker == null) { return; } string buffer = token.GetText(); ILexer wordLexer = new WordLexer(buffer); wordLexer.Start(); while (wordLexer.TokenType != null) { string tokenText = wordLexer.GetCurrTokenText(); if (SpellCheckUtil.ShouldSpellCheck(tokenText, settings.CompiledWordsToIgnore) && !spellChecker.TestWord(tokenText, true)) { IClassMemberDeclaration containingElement = token.GetContainingNode <IClassMemberDeclaration>(false); if (containingElement == null || !IdentifierResolver.IsIdentifier(containingElement, solution, tokenText)) { CamelHumpLexer camelHumpLexer = new CamelHumpLexer(buffer, wordLexer.TokenStart, wordLexer.TokenEnd); foreach (LexerToken humpToken in camelHumpLexer) { if (SpellCheckUtil.ShouldSpellCheck(humpToken.Value, settings.CompiledWordsToIgnore) && !spellChecker.TestWord(humpToken.Value, true)) { //int start = token.GetTreeStartOffset().Offset + wordLexer.TokenStart; //int end = start + tokenText.Length; //var range = new TextRange(start, end); //var documentRange = new DocumentRange(document, range); DocumentRange documentRange = token.GetContainingFile().TranslateRangeForHighlighting(token.GetTreeTextRange()); documentRange = documentRange.ExtendLeft(-wordLexer.TokenStart); documentRange = documentRange.ExtendRight(-1 * (documentRange.GetText().Length - tokenText.Length)); TextRange textRange = new TextRange(humpToken.Start - wordLexer.TokenStart, humpToken.End - wordLexer.TokenStart); //string word = document.GetText(range); string word = documentRange.GetText(); var highlighting = new StringSpellCheckHighlighting( document.GetText(textRange), documentRange, humpToken.Value, textRange, solution, spellChecker, settingsStore); var file = token.GetContainingFile(); highlightingConsumer.AddHighlighting(highlighting, documentRange, file); break; } } } } wordLexer.Advance(); } }
public override void Report(IHighlightingConsumer consumer) { if (CanUseIndividualReports()) { foreach (var componentBoxing in ComponentBoxings) { componentBoxing.Report(consumer); } return; } var singleBoxing = TryFindSingleOrdinaryBoxing(); if (singleBoxing != null) { var reason = singleBoxing.Reason; if (!singleBoxing.IsPossible) { var description = $"tuple component {reason} performs boxing of the value type"; consumer.AddHighlighting(new BoxingAllocationHighlighting(CorrespondingNode, description)); } else { var description = $"tuple component {reason} possibly performs boxing of the value type"; consumer.AddHighlighting(new PossibleBoxingAllocationHighlighting(CorrespondingNode, description)); } return; } var isAllPossible = IsAllPossible; using var builder = PooledStringBuilder.GetInstance(); builder.Append("tuple conversion contains component type conversions that perform "); if (isAllPossible) { builder.Append("possible "); } builder.AppendLine("boxing of the value types"); AppendReasons(builder.Builder, indent: " ", presentPossible: IsAnyPossible && !isAllPossible); var longDescription = builder.ToString().Trim(); if (isAllPossible) { consumer.AddHighlighting(new PossibleBoxingAllocationHighlighting(CorrespondingNode, longDescription)); } else { consumer.AddHighlighting(new BoxingAllocationHighlighting(CorrespondingNode, longDescription)); } bool CanUseIndividualReports() { foreach (var componentBoxing in ComponentBoxings) { if (componentBoxing.CorrespondingNode == CorrespondingNode) { return(false); } } return(true); }
protected override void AddHighlighting(IHighlightingConsumer consumer, ICSharpDeclaration declaration, string text, string tooltip, DaemonProcessKind kind) { consumer.AddImplicitConfigurableHighlighting(declaration); consumer.AddHighlighting(new UnityGutterMarkInfo(GetActions(declaration), declaration, tooltip)); }
protected override void Run(ICSharpFunctionDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { if (element.Body == null) { return; } var elementProcessor = new ElementProcessor( element, consumer); element.Body.ProcessDescendants(elementProcessor); var store = data.SettingsStore; var baseThreshold = store.GetValue((CognitiveComplexityAnalysisSettings s) => s.CSharpThreshold); var lowThreshold = store.GetValue((CognitiveComplexityAnalysisSettings s) => s.LowComplexityThreshold); var middleThreshold = store.GetValue((CognitiveComplexityAnalysisSettings s) => s.MiddleComplexityThreshold); var highThreshold = store.GetValue((CognitiveComplexityAnalysisSettings s) => s.HighComplexityThreshold); var complexityPercentage = (int)(elementProcessor.ComplexityScore * 100.0 / baseThreshold); string codeLensText; IconId iconId; if (complexityPercentage >= highThreshold) { iconId = ComplexityExtreme.Id; codeLensText = complexityPercentage >= highThreshold * 2 ? $"refactor me? ({complexityPercentage}%)" : $"very complex ({complexityPercentage}%)"; } else if (complexityPercentage >= middleThreshold) { iconId = ComplexityHigh.Id; codeLensText = $"mildly complex ({complexityPercentage}%)"; } else if (complexityPercentage >= lowThreshold) { iconId = ComplexityAverage.Id; codeLensText = $"simple enough ({complexityPercentage}%)"; } else { iconId = ComplexityLow.Id; codeLensText = string.Empty; } if (complexityPercentage > 100) { consumer.AddHighlighting(new CognitiveComplexityHighlighting(element, complexityPercentage)); } #if RIDER var moreText = $"Cognitive complexity value of {elementProcessor.ComplexityScore} " + $"({complexityPercentage}% of threshold {baseThreshold})"; consumer.AddHighlighting( new CodeInsightsHighlighting( element.GetNameDocumentRange(), codeLensText, moreText, moreText, _overallProvider, element.DeclaredElement, _iconHost.Transform(iconId)) ); #endif }
public static void CreateInefficientMultidimensionalArrayAccessWarning([CanBeNull] IDeclaredElement declaredElement, [NotNull] IVariableDeclaration variableDeclaration, [NotNull] IDaemonProcess daemonProcess, [NotNull] DaemonProcessKind kind, [NotNull] IHighlightingConsumer consumer, [NotNull] DocumentRange highlightingRange) { if (declaredElement == null) { return; } var type = variableDeclaration.Type as IArrayType; if (type == null) { return; } if (type.Rank == 1) { return; } IArrayCreationExpression arrayCreationExpression = null; IMultipleDeclaration multipleDeclaration = null; switch (variableDeclaration) { case IFieldDeclaration fieldDeclaration: // perfomance optimization if (fieldDeclaration.GetAccessRights() != AccessRights.PRIVATE) { return; } arrayCreationExpression = (fieldDeclaration.Initial as IExpressionInitializer)?.Value as IArrayCreationExpression; multipleDeclaration = MultipleFieldDeclarationNavigator.GetByDeclarator(fieldDeclaration); break; case ILocalVariableDeclaration localVariableDeclaration: var initial = localVariableDeclaration.Initial; arrayCreationExpression = (initial as IExpressionInitializer)?.Value as IArrayCreationExpression; if (initial != null && arrayCreationExpression == null) { return; } multipleDeclaration = MultipleLocalVariableDeclarationNavigator.GetByDeclarator(localVariableDeclaration); break; default: return; } var classDeclaration = variableDeclaration.GetContainingNode <IClassLikeDeclaration>(); if (classDeclaration == null) { return; } var usages = FindArrayUsages(declaredElement, classDeclaration, daemonProcess, kind); foreach (var usage in usages) { if (ElementAccessExpressionNavigator.GetByOperand(usage as ICSharpExpression) == null) { return; } } if (arrayCreationExpression.ContainsErrorElement()) { return; } consumer.AddHighlighting(new InefficientMultidimensionalArrayUsageWarning(usages.Select(t => t.CreateTreeElementPointer()).ToList(), arrayCreationExpression, variableDeclaration, multipleDeclaration, highlightingRange)); }
/// <summary> /// Adds the highlighting. /// </summary> ///<param name="consumer">The consumer.</param> ///<param name="highlighting">The highlighting.</param> private static void AddHighlighting(IHighlightingConsumer consumer, SuggestionBase highlighting) { var range = highlighting.Range; if (!range.IsValid()) { return; } consumer.AddHighlighting(range, highlighting); }
protected override void Analyze(IMemberOwnerDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { var typeElement = element.DeclaredElement; if (typeElement == null) { return; } if (!Api.IsUnityType(typeElement)) { return; } var map = new OneToListMap <UnityEventFunction, Candidate>(new UnityEventFunctionKeyComparer()); foreach (var member in typeElement.GetMembers()) { if (member is IMethod method) { var unityEventFunction = Api.GetUnityEventFunction(method, out var match); if (unityEventFunction != null) { map.Add(unityEventFunction, new Candidate(method, match)); } } } foreach (var pair in map) { var function = pair.Key; var candidates = pair.Value; if (candidates.Count == 1) { // Only one function, mark it as a unity function, even if it's not an exact match // We'll let other inspections handle invalid signatures var method = candidates[0].Method; AddGutterMark(consumer, method, function); AddMethodSignatureInspections(consumer, method, function, candidates[0].Match); } else { var hasExactMatch = false; // All exact matches should be marked as an event function var duplicates = new FrugalLocalList <IMethod>(); foreach (var candidate in candidates) { if (candidate.Match == MethodSignatureMatch.ExactMatch) { AddGutterMark(consumer, candidate.Method, function); hasExactMatch = true; duplicates.Add(candidate.Method); } } // Multiple exact matches should be marked as duplicate/ambiguous if (duplicates.Count > 1) { foreach (var method in duplicates) { foreach (var declaration in method.GetDeclarations()) { consumer.AddHighlighting( new DuplicateEventFunctionWarning((IMethodDeclaration)declaration)); } } } // If there are no exact matches, mark all as unity functions, with inspections // to fix up signature errors if (!hasExactMatch) { foreach (var candidate in candidates) { var method = candidate.Method; AddGutterMark(consumer, method, function); AddMethodSignatureInspections(consumer, method, function, candidate.Match); } } } } }
public override void VisitNode(ITreeNode node, IHighlightingConsumer context) { base.VisitNode(node, context); DocumentRange highlightingRange = node.GetHighlightingRange(); //context.AddHighlighting(new PredefinedHighlighting(VsPredefinedHighlighterIds.RazorCode), highlightingRange); string attributeId = GetHighlightingAttributeId(node); if (attributeId != null) context.AddHighlighting(new PredefinedHighlighting(attributeId), highlightingRange); }
private void AddHighlighting([NotNull] IHighlightingConsumer consumer, [NotNull] ITreeNode expression) { consumer.AddHighlighting(new PsiErrorElementHighlighting(expression), File); }
protected override bool CheckAndAnalyze(IInvocationExpression invocationExpression, IHighlightingConsumer consumer) { //algorithm: //if conditional qualifier is open type // return // REASON: burst allows to instantiate generics only with structures. if it is instantiated with class - // it would be highlighted where generics called. if it is instantiated with structure - 2 possible outcomes. // if there are no generic constraints - only object methods can be called, they are handled in BurstReferenceExpressionAnalyzer. // If there is some interface constraint - then it is ok, Burst allows to call interface methods if they are implemented with struct. // CallGraph would have edges to interface through constraints, not instantiation. //else // if condional qualifier is class // if conditiinal qualifier is class instance // return // REASON: I will highlight refereceExpression, which would have ReadAccess. Burst can't access // managed objects. // else // if function non static // then it would be highlighted as error // else // ok. burst allows invoking static functions. // else // if conditional qualifier is struct instance // if function is virtual/abstract/override // HIGHLIGHT: invocation expressio WITHOUT parameters // ALSO: struct's method are implicitle sealed! // REASON: burst does not support any invocations that use virtual table. // IMPORTANT: type parameters and open types may have some virtual invocations, // but burst generic system allows only structures/primitives to instatiate generics. // Structure/primitives DOES support some virtual methods from System.Object. // else // it is ok. burst allows any method from structure // else // if function non static // then it would be highlighted as error // else // ok. burst alows invoking static functions. var invokedMethod = CallGraphUtil.GetCallee(invocationExpression) as IMethod; if (invokedMethod == null) { return(false); } if (IsDebugLog(invokedMethod)) { var argumentList = invocationExpression.ArgumentList.Arguments; if (argumentList.Count != 1) { return(false); } var argument = argumentList[0]; if (IsBurstPermittedString(argument.Expression?.Type())) { return(false); } consumer?.AddHighlighting(new BurstDebugLogInvalidArgumentWarning(argument.Expression.GetDocumentRange())); return(true); } if (IsStringFormat(invokedMethod)) { var argumentList = invocationExpression.ArgumentList.Arguments; var isWarningPlaced = BurstStringLiteralOwnerAnalyzer.CheckAndAnalyze(invocationExpression, new BurstManagedStringWarning(invocationExpression.GetDocumentRange()), consumer); if (isWarningPlaced) { return(true); } if (argumentList.Count == 0) { return(false); } var firstArgument = argumentList[0]; var cSharpLiteralExpression = firstArgument.Expression as ICSharpLiteralExpression; if (cSharpLiteralExpression != null && cSharpLiteralExpression.Literal.GetTokenType().IsStringLiteral) { return(false); } consumer?.AddHighlighting(new BurstDebugLogInvalidArgumentWarning(firstArgument.Expression.GetDocumentRange())); return(true); } if (IsObjectMethodInvocation(invocationExpression)) { consumer?.AddHighlighting(new BurstAccessingManagedMethodWarning(invocationExpression.GetDocumentRange(), invokedMethod.ShortName, invokedMethod.GetContainingType()?.ShortName)); return(true); } if (IsReturnValueBurstProhibited(invokedMethod) || HasBurstProhibitedArguments(invocationExpression.ArgumentList)) { consumer?.AddHighlighting(new BurstFunctionSignatureContainsManagedTypesWarning(invocationExpression.GetDocumentRange(), invokedMethod.ShortName)); return(true); } return(false); }
private static void CheckExpression([NotNull] ICSharpExpression expression, [NotNull] IHighlightingConsumer consumer) { var targetType = expression.GetImplicitlyConvertedTo(); if (!targetType.IsReferenceType()) { return; } var expressionType = expression.Type(); if (expressionType.IsUnknown) { return; } if (targetType.IsDelegateType()) { var referenceExpression = expression as IReferenceExpression; var method = referenceExpression?.Reference.Resolve().DeclaredElement as IMethod; if (method == null || method.IsStatic || method.IsExtensionMethod) { return; } ITypeElement valueType = null; var qualifierExpression = referenceExpression.QualifierExpression; if (qualifierExpression == null || qualifierExpression is IBaseExpression) { var declaration = expression.GetContainingTypeDeclaration(); if (declaration != null) { valueType = declaration.DeclaredElement as IStruct; } } else { var type = qualifierExpression.Type() as IDeclaredType; if (type != null) { valueType = type.GetTypeElement(); } } if (valueType != null) { var sourceType = TypeFactory.CreateType(valueType); if (sourceType.IsValueType()) { var description = BakeDescription( "conversion of value type '{0}' instance method to '{1}' delegate type", sourceType, targetType); consumer.AddHighlighting( new BoxingAllocationHighlighting(expression, description), referenceExpression.NameIdentifier.GetDocumentRange()); } } } else { if (targetType.IsUnknown || targetType.Equals(expressionType)) { return; } var conversionRule = expression.GetTypeConversionRule(); if (conversionRule.IsBoxingConversion(expressionType, targetType)) { // there is no boxing conversion here: using (new DisposableStruct()) { } var usingStatement = UsingStatementNavigator.GetByExpression(expression.GetContainingParenthesizedExpression()); if (usingStatement != null) { return; } if (HeapAllocationAnalyzer.IsIgnoredContext(expression)) { return; } var description = BakeDescription("conversion from value type '{0}' to reference type '{1}'", expressionType, targetType); consumer.AddHighlighting( new BoxingAllocationHighlighting(expression, description), expression.GetExpressionRange()); } } }
protected override bool CheckAndAnalyze(ITypeofExpression typeofExpression, IHighlightingConsumer consumer) { consumer?.AddHighlighting(new BurstTypeofExpressionWarning(typeofExpression)); return(true); }
public static void AddImplicitConfigurableHighlighting(this IHighlightingConsumer consumer, ICSharpDeclaration declaration) { consumer.AddHighlighting(new UnityImplicitlyUsedIdentifierHighlighting(declaration.NameIdentifier.GetDocumentRange())); }
public override void VisitPsiExpression(IPsiExpression psiExpression, IHighlightingConsumer consumer) { ITreeNode child = psiExpression.FirstChild; IList<ISequence> list = new List<ISequence>(); while (child != null) { if (child is ISequence) { list.Add(child as ISequence); } if (child is IChoiceTail) { list.Add((child as IChoiceTail).Sequence); } child = child.NextSibling; } if (list.Count > 1) { ISequence[] sequences = list.ToArray(); var isRepeated = new bool[sequences.Count()]; for (int i = 0 ; i < sequences.Count() - 1 ; ++i) { if (!isRepeated[i]) { ISequence sequence1 = sequences[i]; for (int j = i + 1 ; j < sequences.Count() ; ++j) { ISequence sequence2 = sequences[j]; if (PsiTreeUtil.EqualsElements(sequence1, sequence2)) { if (!isRepeated[i]) { consumer.AddHighlighting(new RepeatedChoiceWarning(sequence1), File); isRepeated[i] = true; } consumer.AddHighlighting(new RepeatedChoiceWarning(sequence2), File); isRepeated[j] = true; } } } } } base.VisitPsiExpression(psiExpression, consumer); }
public void AddInspectorHighlighting(IHighlightingConsumer consumer, ICSharpDeclaration element, IDeclaredElement declaredElement, string baseDisplayName, string baseTooltip, string moreText, IconModel iconModel, IEnumerable <BulbMenuItem> items, List <CodeLensEntryExtraActionModel> extraActions) { string displayName = null; var solution = element.GetSolution(); Assertion.Assert(solution.Locks.IsReadAccessAllowed(), "ReadLock required"); var field = (declaredElement as IField).NotNull(); var type = field.Type; var containingType = field.GetContainingType(); if (containingType == null) { base.AddHighlighting(consumer, element, field, baseDisplayName, baseTooltip, moreText, iconModel, items, extraActions); return; } var(guidN, propertyNames) = GetAssetGuidAndPropertyName(solution, field); if (guidN == null || propertyNames.Length == 0) { base.AddHighlighting(consumer, element, field, baseDisplayName, baseTooltip, moreText, iconModel, items, extraActions); return; } var guid = guidN.Value; var presentationType = GetUnityPresentationType(type); if (!myDeferredCacheController.CompletedOnce.Value || ShouldShowUnknownPresentation(presentationType)) { base.AddHighlighting(consumer, element, field, baseDisplayName, baseTooltip, moreText, iconModel, items, extraActions); return; } if (presentationType == UnityPresentationType.UnityEvent) { var count = myUnityEventsElementContainer.GetUsageCountForEvent(field, out var estimated); var sb = new StringBuilder(); if (count == 0 && !estimated) { sb.Append("No methods"); } else { sb.Append(count); if (estimated) { sb.Append('+'); } sb.Append(" "); sb.Append("method"); if (estimated || count > 1) { sb.Append("s"); } } consumer.AddHighlighting(new UnityInspectorCodeInsightsHighlighting(element.GetNameDocumentRange(), sb.ToString(), GetTooltip(count, estimated, false), "Methods", this, declaredElement, iconModel, presentationType)); return; } var initializer = (element as IFieldDeclaration).NotNull("element as IFieldDeclaration != null").Initial; var initValue = (initializer as IExpressionInitializer)?.Value?.ConstantValue.Value; var initValueUnityPresentation = GetUnitySerializedPresentation(presentationType, initValue); int changesCount; bool isEstimated = false; bool isUniqueChange = false; if (myInspectorValuesContainer.IsIndexResultEstimated(guid, containingType, propertyNames)) { changesCount = myInspectorValuesContainer.GetAffectedFiles(guid, propertyNames) - myInspectorValuesContainer.GetAffectedFilesWithSpecificValue(guid, propertyNames, initValueUnityPresentation); displayName = $"Changed in {changesCount}+ assets"; isEstimated = true; } else { changesCount = 0; var initValueCount = myInspectorValuesContainer.GetValueCount(guid, propertyNames, initValueUnityPresentation); if (initValueCount == 0 && myInspectorValuesContainer.GetUniqueValuesCount(guid, propertyNames) == 1) // only modified value { isUniqueChange = true; var value = myInspectorValuesContainer.GetUniqueValueDifferTo(guid, propertyNames, null); displayName = value.GetPresentation(solution, field, false); } else if (initValueCount > 0 && myInspectorValuesContainer.GetUniqueValuesCount(guid, propertyNames) == 2) { isUniqueChange = true; // original value & only one modified value var anotherValueWithLocation = myInspectorValuesContainer.GetUniqueValueDifferTo(guid, propertyNames, initValueUnityPresentation); displayName = anotherValueWithLocation.GetPresentation(solution, field, false); } if (displayName == null || displayName.Equals("...")) { changesCount = myInspectorValuesContainer.GetAffectedFiles(guid, propertyNames) - myInspectorValuesContainer.GetAffectedFilesWithSpecificValue(guid, propertyNames, initValueUnityPresentation); if (changesCount == 0) { displayName = "Unchanged"; } else { var word = NounUtil.ToPluralOrSingularQuick(changesCount, "asset", "assets"); displayName = $"Changed in {changesCount} {word}"; } } } consumer.AddHighlighting(new UnityInspectorCodeInsightsHighlighting(element.GetNameDocumentRange(), displayName, GetTooltip(changesCount, isEstimated, isUniqueChange), "Property Inspector values", this, declaredElement, iconModel, presentationType)); }
protected override void Analyze(IInvocationExpression expression, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { // Don't do anything unless we have a valid method invocation if (expression.RPar == null) { return; } if (!(expression.InvokedExpression is IReferenceExpression) || expression.TypeArguments.Count != 0) { return; } var literalExpressionArgument = expression.Arguments.SingleItem?.Value as ILiteralExpression; if (literalExpressionArgument == null || !literalExpressionArgument.Literal.IsAnyStringLiteral()) { return; } // GameObject.GetComponent, Component.GetComponent, GameObject.AddComponent and ScriptableObject.CreateInstance. // Decided by who gets references in a string literal argument by the UnityObjectTypeOrNamespaceReference provider. var methodName = GetMethodName(expression.Reference); if (methodName != "GetComponent" && methodName != "AddComponent" && methodName != "CreateInstance") { return; } // Don't add the quick fix in the case of the following, because we can't fix it cleanly: // GetComponent( // #if DEBUG // "MyDebugComponent" // #else // "MyReleaseComponent" // #endif // ) if (expression.ContainsPreprocessorDirectives()) { return; } var references = literalExpressionArgument.GetReferences <UnityObjectTypeOrNamespaceReference>(); // Don't add anything unless ALL references resolve properly foreach (var reference in references) { var resolveInfo = reference.Resolve(); if (!resolveInfo.Info.ResolveErrorType.IsAcceptable) { return; } } foreach (var reference in references) { var resolveInfo = reference.Resolve(); if (resolveInfo.DeclaredElement is ITypeElement typeElement) { consumer.AddHighlighting(new PreferGenericMethodOverloadWarning(expression, methodName, literalExpressionArgument, typeElement)); } } }
void AnalyzeWhenExpressionIsKnownToBeTrueOrFalse( [NotNull] IHighlightingConsumer context, [CanBeNull] CSharpCompilerNullableInspector nullabilityInspector, [CanBeNull] CSharpControlFlowGraphInspector inspector, [CanBeNull][ItemNotNull] HashSet <IAsExpression> alwaysSuccessTryCastExpressions, [NotNull] Assertion assertion, bool isKnownToBeTrue) { if (assertion is AssertionStatement assertionStatement) { // pattern: Assert(true); or Assert(false); Debug.Assert(CSharpTokenType.TRUE_KEYWORD != null); Debug.Assert(CSharpTokenType.FALSE_KEYWORD != null); if (IsLiteral(assertionStatement.Expression, isKnownToBeTrue ? CSharpTokenType.TRUE_KEYWORD : CSharpTokenType.FALSE_KEYWORD)) { context.AddHighlighting( new RedundantAssertionStatementSuggestion( $"Assertion is redundant because the expression is {(isKnownToBeTrue ? "true" : "false")} here.", assertionStatement)); } if (assertionStatement.Expression is IEqualityExpression equalityExpression) { // pattern: Assert(x != null); when x is known to be null or not null Debug.Assert(CSharpTokenType.NULL_KEYWORD != null); var expression = TryGetOtherOperand(equalityExpression, EqualityExpressionType.NE, CSharpTokenType.NULL_KEYWORD); if (expression != null) { switch (GetExpressionNullReferenceState( nullabilityInspector, inspector, alwaysSuccessTryCastExpressions, expression)) { case CSharpControlFlowNullReferenceState.NOT_NULL: if (isKnownToBeTrue) { context.AddHighlighting( new RedundantAssertionStatementSuggestion( "Assertion is redundant because the expression is true here.", assertionStatement)); } break; case CSharpControlFlowNullReferenceState.NULL: if (!isKnownToBeTrue) { context.AddHighlighting( new RedundantAssertionStatementSuggestion( "Assertion is redundant because the expression is false here.", assertionStatement)); } break; } } // pattern: Assert(x == null); when x is known to be null or not null expression = TryGetOtherOperand(equalityExpression, EqualityExpressionType.EQEQ, CSharpTokenType.NULL_KEYWORD); if (expression != null) { switch (GetExpressionNullReferenceState(nullabilityInspector, inspector, alwaysSuccessTryCastExpressions, expression)) { case CSharpControlFlowNullReferenceState.NOT_NULL: if (!isKnownToBeTrue) { context.AddHighlighting( new RedundantAssertionStatementSuggestion( "Assertion is redundant because the expression is false here.", assertionStatement)); } break; case CSharpControlFlowNullReferenceState.NULL: if (isKnownToBeTrue) { context.AddHighlighting( new RedundantAssertionStatementSuggestion( "Assertion is redundant because the expression is true here.", assertionStatement)); } break; } } } } }
public static bool CheckAndAnalyze(ITreeNode node, IHighlighting highlighting, IHighlightingConsumer consumer) { var firstNode = node; do { var parent = node.Parent; if (parent is IExpressionInitializer expressionInitializer) { if (ReferenceEquals(expressionInitializer.Value, firstNode)) { do { node = parent; parent = node.Parent; } while (parent != null && !(parent is IInitializerOwnerDeclaration)); if (parent == null) { return(true); } var initializerOwnerDeclaration = (IInitializerOwnerDeclaration)parent; if (ReferenceEquals(initializerOwnerDeclaration.Initializer, expressionInitializer)) { var typeOwner = initializerOwnerDeclaration.DeclaredElement as ITypeOwner; var type = typeOwner?.Type; if (BurstCodeAnalysisUtil.IsFixedString(type)) { return(false); } } } consumer?.AddHighlighting(highlighting); return(true); } if (parent is ICSharpArgument cSharpArgument) { var invocationInfo = cSharpArgument.Invocation; if (invocationInfo is IInvocationExpression info) { var callee = CallGraphUtil.GetCallee(info) as IMethod; if (BurstCodeAnalysisUtil.IsBurstPermittedString(cSharpArgument.GetExpressionType().ToIType()) && callee != null && (BurstCodeAnalysisUtil.IsDebugLog(callee) || BurstCodeAnalysisUtil.IsStringFormat(callee))) { return(false); } } consumer?.AddHighlighting(highlighting); return(true); } if (parent is IAssignmentExpression assignmentExpression) { if (assignmentExpression.Dest == node) { return(false); } if (BurstCodeAnalysisUtil.IsFixedString(assignmentExpression.Dest.Type()) && assignmentExpression.Source.Type().IsString()) { return(false); } consumer?.AddHighlighting(highlighting); return(true); } if (parent is ITypeMemberDeclaration) { consumer?.AddHighlighting(highlighting); return(true); } node = parent; } while (node != null); consumer?.AddHighlighting(highlighting); return(true); }
protected override void Run(IArrayInitializer element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { if (element.InitializerElements.Count > 0) { IType arrayElementType; switch (element.Parent) { case ITypeOwnerDeclaration declaration: arrayElementType = declaration.Type.GetScalarType(); if (arrayElementType == null) { return; } break; case IArrayCreationExpression creationExpression: arrayElementType = creationExpression.GetElementType(); break; default: return; } if (element.InitializerElements.All( initializerElement => initializerElement?.FirstChild != null && initializerElement.FirstChild.IsDefaultValueOf(arrayElementType))) { // { d, default, default(T) } // where d is the default value for the T var builder = new StringBuilder(); builder.Append("new "); Debug.Assert(CSharpLanguage.Instance != null); builder.Append(arrayElementType.GetPresentableName(CSharpLanguage.Instance)); if (builder[builder.Length - 1] != '?') { var isNullableReferenceType = element.IsNullableAnnotationsContextEnabled() && arrayElementType.Classify == TypeClassification.REFERENCE_TYPE && arrayElementType.NullableAnnotation == NullableAnnotation.NotAnnotated; if (isNullableReferenceType) { builder.Append('?'); } } else { // workaround for R# 2020.2 if (element.IsNullableAnnotationsContextEnabled()) { switch (arrayElementType.Classify) { case TypeClassification.UNKNOWN: case TypeClassification.VALUE_TYPE when !arrayElementType.IsNullable(): builder.Remove(builder.Length - 1, 1); break; } } } builder.Append('['); builder.Append(element.InitializerElements.Count); builder.Append(']'); var suggestedCode = builder.ToString(); consumer.AddHighlighting( new ArrayWithDefaultValuesInitializationSuggestion(CreateHighlightingMessage(suggestedCode), suggestedCode, element)); } } }