Es ist bereits Tradition geworden, dass Programmierer, die das PVS-Studio-Team auffüllen, ihre Arbeit mit dem Schreiben eines Artikels über die Analyse eines Open-Source-Projekts beginnen. Dieses Mal wird ein solch bewährtes Projekt die Telerik-Benutzeroberfläche für UWP sein.
PVS-Studio Code Analyzer
PVS-Studio ist ein Tool zum Erkennen von Fehlern und potenziellen Schwachstellen im Quellcode von Programmen, die in C, C ++, C # und Java geschrieben wurden. Läuft unter Windows, Linux und MacOS.
Der Analysator bietet verschiedene Verwendungsszenarien:
- kann lokal auf Entwicklungsmaschinen verwendet werden und als Plug-In in Visual Studio oder IntelliJ IDEA integriert werden;
- kann in die SonarQube-Plattform für kontinuierliche Qualitätssicherung integriert werden;
- kann unabhängig verwendet werden und in das Montagesystem integriert werden;
- Es ist möglich, das Dienstprogramm zur Kompilierungsüberwachung zu verwenden.
- Die Integration mit Azure DevOps, Jenkins, TeamCity, Travis CI und ähnlichen Systemen ist möglich.
- usw.
Geprüftes Projekt
Telerik UI for UWP ist eine Reihe von Benutzeroberflächenkomponenten für die Universal Windows Platform (UWP). Der Quellcode für das Projekt ist
auf Github zu
finden . Das Set enthält mehr als 20 Komponenten, mit denen Sie Daten in Form von Diagrammen visualisieren, Listen und Tabellen erstellen und mithilfe einer Karte Daten demonstrieren können, die einem Standort zugeordnet sind.
Fragmente, die beim Studium des Analysatorberichts Aufmerksamkeit erregt haben
PVS-Studio Warnung :
V3013 Es ist merkwürdig, dass der Hauptteil der Funktion 'OnMinValuePropertyChanged' dem Hauptteil der Funktion 'OnMaxValuePropertyChanged' vollständig entspricht. RadGauge.cs 446
private static void OnMinValuePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args) { double newVal = (double)args.NewValue; ValidateValue(newVal); RadGauge gauge = sender as RadGauge; if (gauge.panel != null) { gauge.panel.UpdateOnMinMaxValueChange(); } if(AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged)) { var peer = FrameworkElementAutomationPeer.FromElement(gauge) as RadGaugeAutomationPeer; if (peer != null) { peer.RaiseMinimumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue); } } } private static void OnMaxValuePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args) { double newVal = (double)args.NewValue; ValidateValue(newVal); RadGauge gauge = sender as RadGauge; if (gauge.panel != null) { gauge.panel.UpdateOnMinMaxValueChange(); } if (AutomationPeer.ListenerExists(AutomationEvents.PropertyChanged)) { var peer = FrameworkElementAutomationPeer.FromElement(gauge) as RadGaugeAutomationPeer; if (peer != null) { peer.RaiseMinimumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue); } } }
Der Analysator hat zwei Methoden erkannt,
OnMinValuePropertyChanged und
OnMaxValuePropertyChanged , die dieselben Aktionen ausführen. Ich habe den starken Verdacht, dass sich ein Fehler in diesen Code eingeschlichen hat. Beachten Sie, dass sowohl die
OnMinValuePropertyChanged- Methode als auch die
OnMaxValuePropertyChanged- Methode
RaiseMinimumPropertyChangedEvent verwenden . Gleichzeitig finden
Sie in der
RadGaugeAutomationPeer- Klasse sowohl eine Methode für "Minimum" als auch für "Maximum":
internal void RaiseMaximumPropertyChangedEvent(double oldValue, double newValue) { this.RaisePropertyChangedEvent( RangeValuePatternIdentifiers.MaximumProperty, oldValue, newValue); } internal void RaiseMinimumPropertyChangedEvent(double oldValue, double newValue) { this.RaisePropertyChangedEvent( RangeValuePatternIdentifiers.MinimumProperty, oldValue, newValue); }
Die
RaiseMaximumPropertyChangedEvent- Methode wird im Code nie verwendet,
RaiseMinimumPropertyChangedEvent wird jedoch zweimal verwendet. Und, wissen Sie, die Leistung der
OnMaxValuePropertyChanged- Methode wirft Fragen auf ... Ich denke, sie sollte Folgendes schreiben:
private static void OnMaxValuePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args) { .... peer.RaiseMaximumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue); .... }
Trotzdem sieht der Code aufgrund der großen Anzahl sich wiederholender Elemente nicht sehr ordentlich aus. Es ist schwer zu verstehen, und wiederholte Zeilen trüben die Aufmerksamkeit des Programmierers, und es wird schwieriger, unter solchen Bedingungen eine Codeüberprüfung durchzuführen. Die statischen Analysetools können diesen Code jedoch hervorragend überprüfen (dies bedeutet jedoch nicht, dass Sie auf Refactoring und insbesondere auf die Reduzierung der Anzahl wiederholter Zeilen verzichten können).
Aus dem obigen und dem folgenden Codeausschnitt können wir annehmen, dass die Autoren dem Kopieren und Einfügen nicht abgeneigt sind. Wie wir alle ... :)
PVS-Studio Warnung :
V3001 Links und rechts von '||' befinden sich identische Unterausdrücke 'element.RenderSize == emptySize'. Betreiber. TiltInteractionEffect.cs 181
private static bool IsPointInElementBounds(FrameworkElement element, Point position) { Size emptySize = new Size(0, 0); if (element.RenderSize == emptySize || element.RenderSize == emptySize) { return false; } return new Rect(....).Contains(position); }
Der Analysator hat ein Fehlercodefragment erkannt, in dem sich rechts und links vom Operator '||' befindet Die if-
Anweisung verwendet dieselben Unterausdrücke. Der zweite Unterausdruck hätte eindeutig anders aussehen sollen. Vielleicht sollte anstelle des zweiten
RenderSize DesiredSize sein . Oder es sollte überhaupt keinen zweiten Unterausdruck geben. In jedem Fall muss dieser Code repariert werden.
PVS-Studio Warnung :
V3001 Links und rechts vom '||' befinden sich identische Unterausdrücke 'text [0] ==' - ''. Betreiber. RadNumericBox.cs 1057
private void ValidateText() { string text = this.textBox.Text; .... if (text.Length == 1 && (text[0] == '-' || text[0] == '-')) { if (this.isNegative) { this.isNegative = false; } else { this.SetText(string.Empty); } return; } .... }
Hier schreibt der Entwickler den im Textfeld eingegebenen Text in eine Variable. Dann wird das erste Zeichen der Zeichenfolge zweimal mit demselben Zeichen '-' verglichen, was eine verdächtige Entscheidung ist. Offensichtlich funktioniert die Textüberprüfung in dieser Funktion nicht wie ursprünglich beabsichtigt.
PVS-Studio Warnung :
V3001 Links und rechts vom Operator '&&' befinden sich identische Unterausdrücke 'newValue.HasValue'. DateTimePicker.cs 576
private static void OnValueChanged(object sender, DependencyPropertyChangedEventArgs args) { DateTimePicker picker = sender as DateTimePicker; var newValue = (DateTime?)args.NewValue; if (newValue.HasValue && newValue != null)
Der Ausdruck
newValue.HasValue gibt
true zurück
, wenn
newValue einen Wert enthält, und der Ausdruck
newValue! = Null macht dasselbe. Der Analysator achtet darauf, und was zu tun ist, ist, einen der Unterausdrücke zu entfernen oder durch einen anderen zu ersetzen (wenn etwas anderes überprüft werden musste), liegt es an den Entwicklern, zu entscheiden.
PVS-Studio Warnung :
V3125 Das Objekt 'CurrentAttachedMenu' wurde verwendet, nachdem es gegen null überprüft wurde. Überprüfen Sie die Zeilen: 98, 96. PopupService.cs 98
internal static class PopupService { .... private static void Overlay_PointerPressed(....) { if (CurrentAttachedMenu == null || !CurrentAttachedMenu.hitTestService. HitTest(e.GetCurrentPoint(CurrentAttachedMenu).Position).Any()) { CurrentAttachedMenu.IsOpen = false; HideOverlay(); } } }
Wenn sich herausstellt, dass die Variable
CurrentAttachedMenu null ist ,
löst die Auswertung des Ausdrucks
CurrentAttachedMenu.IsOpen eine Ausnahme aus. Auf den ersten Blick scheint dies ein einfacher Tippfehler zu sein und bedeutete keinen Vergleich mit
null , sondern die inverse Operation - '! ='. In der Bedingung der
if-Anweisung tritt jedoch eine Ausnahme auf, wenn die Variable
CurrentAttachedMenu null ist .
Weiter im Code gab es weitere
37 der gleichen Warnungen, von denen einige auf Fehler hinweisen. Aber sie im Rahmen eines Artikels zu beschreiben, ist immer noch zu viel, deshalb werde ich sie unbeaufsichtigt lassen.
PVS-Studio Warnung :
V3019 Möglicherweise wird eine falsche Variable nach der Typkonvertierung mit dem Schlüsselwort 'as' mit null verglichen. Überprüfen Sie die Variablen 'dragDropElement', 'uiDragDropElement'. DragDrop.cs 91
internal static void StartDrag(....) { var dragDropElement = sender as IDragDropElement; .... UIElement uiDragDropElement = dragDropElement as UIElement; .... if (dragDropElement == null || !dragDropElement.CanStartDrag(trigger, initializeContext)) { return; } .... }
Es ist sehr wahrscheinlich, dass der Autor die Variablen verwechselt hat. Die
Nullungleichung wird nicht durch den Link überprüft, der als Ergebnis der
Umwandlung erhalten wurde , sondern durch das Original (
dragDropElement ). Höchstwahrscheinlich sollte der Link
uiDragDropElement überprüft werden . Die Vermutung wird auch durch die Tatsache bestätigt, dass der Programmierer
uiDragDropElement weiter verwendet
hat, ohne nach
Null zu suchen .
PVS-Studio Warnung :
V3030 Wiederkehrende Prüfung. Die Bedingung '! ShowIndicatorWhenNoData' wurde bereits in Zeile 139 überprüft. RadDataBoundListBox.PullToRefresh.cs 141
internal void HandlePullToRefreshItemStateChanged(object item, ItemState state) { .... bool showIndicatorWhenNoData = this.ShowPullToRefreshWhenNoData; if (this.realizedItems.Count == 0 && !showIndicatorWhenNoData) { if (state == ItemState.Recycled && !showIndicatorWhenNoData) { this.StopPullToRefreshLoading(false); this.HidePullToRefreshIndicator(); } return; } .... }
Der Analysator hat einen Code gefunden, in dem unter zwei Bedingungen dieselbe
showIndicatorWhenNoData- Variable erneut überprüft wird. Vielleicht ist die Prüfung einfach redundant, aber es besteht auch die Möglichkeit, dass einer der doppelten Unterausdrücke überhaupt anders sein sollte.
PVS-Studio Warnung :
V3031 Eine übermäßige Überprüfung kann vereinfacht werden. Das '||' Der Operator ist von entgegengesetzten Ausdrücken umgeben. SelectedItemCollection.cs 77
internal class SelectedItemCollection : ObservableCollection<object> { .... private bool CanInsertItem(object item) { return this.suspendLevel == 0 && this.AllowSelect && ((!this.AllowMultipleSelect && this.Count == 0) || this.AllowMultipleSelect); } }
Dieser Code ist formal nicht fehlerhaft. Der Analysator weist auf eine gewisse Code-Redundanz in der Bedingung hin. Es ist jedoch zu beachten, dass zusätzlicher Code manchmal das Ergebnis eines Fehlers ist, z. B. wenn anstelle einer Variablen eine andere mehrmals überprüft wird.
Sie können diesen Zustand etwas reduzieren und den zusätzlichen Code entfernen. Zum Beispiel so:
internal class SelectedItemCollection : ObservableCollection<object> { .... private bool CanInsertItem(object item) { return this.suspendLevel == 0 && this.AllowSelect && (this.AllowMultipleSelect || this.Count == 0); } }
Andere ähnliche Nachrichten:
- V3031 Eine übermäßige Überprüfung kann vereinfacht werden. Das '||' Der Operator ist von entgegengesetzten Ausdrücken umgeben. SelectedItemCollection.cs 93
- V3031 Eine übermäßige Überprüfung kann vereinfacht werden. Das '||' Der Operator ist von entgegengesetzten Ausdrücken umgeben. StackVirtualizationStrategy.cs 49
- V3031 Eine übermäßige Überprüfung kann vereinfacht werden. Das '||' Der Operator ist von entgegengesetzten Ausdrücken 'state == null' und 'state! = null' umgeben. LocalFieldDescriptionsProviderBase.cs 24
Stellen Sie sich einen anderen Code vor, bei dem der Analysator Folgendes zurückgegeben hat:
PVS-Studio-Warnungen :
- V3137 Die Variable 'leftMargin' wird zugewiesen, aber am Ende der Funktion nicht verwendet. DragDrop.cs 87
- V3137 Die Variable 'topMargin' wird zugewiesen, aber am Ende der Funktion nicht verwendet. DragDrop.cs 88
internal static class DragDrop { .... double leftMargin = 0d; double topMargin = 0d; if (frameworkElementSource != null) { leftMargin = frameworkElementSource.Margin.Left;
Der Analysator meldet, dass den
Variablen leftMargin und
topMargin Werte zugewiesen wurden.
Danach werden diese Variablen jedoch erst am Ende der Methode verwendet. Hier liegt wahrscheinlich kein Fehler vor, aber ein solcher Code sieht verdächtig aus. Dies kann auf einen Tippfehler oder ein erfolgloses Refactoring zurückzuführen sein.
Das gleiche Problem wurde an anderer Stelle gefunden: V3137 Die Variable 'currentColumnLength' wird zugewiesen, aber am Ende der Funktion nicht verwendet. WrapLayout.cs 824
PVS-Studio Warnung :
V3061 Der Parameter 'index' wird vor der Verwendung immer im Methodenkörper neu geschrieben. DataEngine.cs 1443
private static Tuple<Group, int> FindGroupAndItemIndex(.... int index, ....) { if (exhaustiveSearch) { .... } else { var aggregateRowGroup = rowRootGroup; var rowGroupNames = valueProvider.GetRowGroupNames(item); foreach (var groupName in rowGroupNames) { Group group; if (aggregateRowGroup.TryGetGroup(groupName, out group)) { aggregateRowGroup = group; } } index = aggregateRowGroup.IndexOf(item,
Der
Indexparameter der
FindGroupAndItemIndex- Methode
wird vor der Verwendung überschrieben. Dies weist höchstwahrscheinlich auf einen Programmiererfehler hin.
PVS-Studio Warnung :
V3083 Unsicherer Aufruf des Ereignisses 'Abgeschlossen', NullReferenceException ist möglich. Überlegen Sie, ob Sie einer lokalen Variablen ein Ereignis zuweisen möchten, bevor Sie sie aufrufen. ActionBase.cs 32
internal abstract class ActionBase { .... protected virtual void OnCompleted() { this.IsCompleted = true; if (this.Completed != null) { this.Completed(this, EventArgs.Empty); } } }
Der Programmierer hat bei dieser Methode einen möglicherweise unsicheren Aufruf des Ereignishandlers zugelassen, was zu einer Ausnahme vom Typ
NullReferenceException führen kann . Eine Ausnahme wird ausgelöst, sofern dieses Ereignis zwischen der
Nullprüfung und dem Aufruf der Ereignishandler nicht verbleibt.
Es gibt weitere
49 ähnliche Probleme im Code. Es wird nicht interessant sein, alle in diesem Artikel zu sehen, und die Autoren können sie mit PVS-Studio leicht selbst finden, sodass wir zu anderen Fehlern übergehen.
PVS-Studio Warnung :
V3145 Unsichere Dereferenzierung eines WeakReference-Ziels. Überprüfen Sie info.Target. Das Objekt könnte zwischen der Überprüfung von 'IsAlive' und dem Zugriff auf die Eigenschaft 'Target' Müll gesammelt haben. FadeAnimation.cs 84
public class RadFadeAnimation : RadAnimation { .... protected internal override void ApplyAnimationValues(PlayAnimationInfo info) { .... if (info.Target.Opacity != opacity)
Der Analysator warnt vor der Gefahr einer Ausnahme vom Typ
NullReferenceException beim Zugriff auf die Eigenschaft
info.Target.Opacity . Um das Wesentliche des Problems besser zu verstehen, müssen Sie sich Fragmente der
PlayAnimationInfo- Klasse
ansehen , insbesondere die
Target- Eigenschaft.
public class PlayAnimationInfo { .... private WeakReference target; .... public PlayAnimationInfo(Storyboard storyboard, RadAnimation animation, UIElement target) { .... this.target = new WeakReference(target); .... } .... public UIElement Target { get { if (this.target.IsAlive) { return this.target.Target as UIElement; } return null; } } .... }
Je weiter Sie diesen Code ausgraben, desto mehr potenzielle Probleme können Sie im Allgemeinen darin finden. Schauen wir uns das vielleicht interessanteste an - das, an das der Analysator eine Warnung ausgegeben hat. Tatsache ist, dass selbst wenn die Ausführung dem damaligen Zweig der
if-Anweisung folgt, dies nicht garantiert, dass eine Referenz ungleich Null zurückgegeben wird. Unabhängig von Gesprächen über die Besetzung betrachten wir hier alles, was aufgrund der Initialisierung des Objekts im Konstruktor zulässig ist.
Wie ist das möglich? Tatsache ist, dass
this.target.Target null zurückgibt , wenn zwischen der
IsAlive- Prüfung und dem
Target- Aufruf die Garbage Collection ausgeführt wird, unter die das von
WeakReference referenzierte
Objekt fällt . Das heißt, die
IsAlive- Prüfung garantiert nicht, dass das Objekt beim nächsten Zugriff auf das Ziel weiterhin verfügbar ist.
Übrigens ist die Situation
null; fängt eine andere Diagnoseregel ab: V3080 Mögliche Null-Dereferenzierung. Überprüfen Sie 'info.Target'. FadeAnimation.cs 84
Ähnliche Probleme im Code traten mehrmals auf:
- V3145 Unsichere Dereferenzierung eines WeakReference-Ziels. Überprüfen Sie das Ziel. Das Objekt könnte Müll gesammelt worden sein, bevor auf die Eigenschaft 'Target' zugegriffen wurde. MoveXAnimation.cs 80
- V3145 Unsichere Dereferenzierung eines WeakReference-Ziels. Überprüfen Sie das Ziel. Das Objekt könnte Müll gesammelt worden sein, bevor auf die Eigenschaft 'Target' zugegriffen wurde. MoveYAnimation.cs 80
- V3145 Unsichere Dereferenzierung eines WeakReference-Ziels. Überprüfen Sie info.Target. Das Objekt könnte Müll gesammelt worden sein, bevor auf die Eigenschaft 'Target' zugegriffen wurde. PlaneProjectionAnimation.cs 244
- V3145 Unsichere Dereferenzierung eines WeakReference-Ziels. Das Objekt könnte zwischen der Überprüfung von 'IsAlive' und dem Zugriff auf die Eigenschaft 'Target' Müll gesammelt haben. WeakEventHandler.cs 109
Fahren wir mit dem nächsten Beispiel fort.
Warnung PVS-Studio :
V3066 Möglicherweise falsche Reihenfolge der an den Konstruktor 'NotifyCollectionChangedEventArgs' übergebenen Argumente: 'oldItem' und 'newItem'. CheckedItemsCollection.cs 470
public class CheckedItemsCollection<T> : IList<T>, INotifyCollectionChanged { .... private NotifyCollectionChangedEventArgs GenerateArgs(....) { switch (action) { case NotifyCollectionChangedAction.Add: .... case NotifyCollectionChangedAction.Remove: .... case NotifyCollectionChangedAction.Replace: return new NotifyCollectionChangedEventArgs( action, oldItem, newItem, changeIndex);
Um zu verstehen, was diese Warnung des Analysators bedeutet, sollten Sie sich die Konstruktorparameter
NotifyCollectionChangedEventArgs ansehen :
public NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction action, object newItem, object oldItem, int index);
Der Analysator warnt dies im Ausdruck
return new NotifyCollectionChangedEventArgs( action, oldItem, newItem, changeIndex);
tauschte die Variablen
oldItem und
newItem aus . In der Konstruktordefinition werden sie in einer anderen Reihenfolge aufgelistet. Ob dies bewusst gemacht wurde oder nicht, kann man nur erraten.
PVS-Studio Warnung :
V3102 Verdächtiger Zugriff auf das Element des '
x' -Objekts durch einen konstanten Index innerhalb einer Schleife. DataEngine.cs 1718
private class ObjectArrayComparer : IEqualityComparer<object[]> { public bool Equals(object[] x, object[] y) { .... for (int i = 0; i < x.Length; i++) { if (!object.Equals(x[0], y[0]))
Bei jeder Iteration in der Schleife vergleicht der Programmierer
x [0] und
y [0]. Die Schleife ist in diesem Code jedoch nicht sinnvoll, da nur die ersten Elemente verglichen werden. Dies bedeutete höchstwahrscheinlich einen Vergleich der entsprechenden Elemente von Arrays. Dann lautet der richtige Code wie folgt:
for (int i = 0; i < x.Length; i++) { if (!object.Equals(x[i], y[i])) { return false; } }
Warnung PVS-Studio :
V3123 Möglicherweise
funktioniert der Operator '?:' Anders als erwartet. Seine Priorität ist niedriger als die Priorität anderer Betreiber in seinem Zustand. EditRowHostPanel.cs 35
protected override Size MeasureOverride(Size availableSize) { .... bool shouldUpdateRowHeight = editorLine == 0 || displayedElement == null ? false : displayedElement.ContainerType != typeof(DataGridGroupHeader); .... }
Mit der Verwendung des Operators '?:' Ist eine Warnung verbunden. Es hat eine niedrigere Priorität als
! =, ||, ==. Daher wird ein Ausdruck möglicherweise nicht wie vom Programmierer geplant ausgewertet. Anscheinend ist dies in diesem Fall falsch positiv und der Code funktioniert korrekt. Das Lesen eines solchen Codes ist jedoch sehr schwierig und es gibt nie die Gewissheit, dass er richtig verstanden wird. Es fühlt sich so an, als hätte der Entwickler so geschrieben, dass niemand etwas verstanden hat :) Der beste Weg, dies zu tun, ist besser lesbar - verwenden Sie Klammern oder die
if-Anweisung .
PVS-Studio Warnung :
V3078 Die ursprüngliche Sortierreihenfolge geht nach wiederholtem Aufruf der 'OrderBy'-Methode verloren. Verwenden Sie die 'ThenBy'-Methode, um die ursprüngliche Sortierung beizubehalten. GridModel.Selection.cs 107
internal partial class GridModel { private void BuildCellSelectionRegions(....) { .... this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .OrderBy(c => c.RowItemInfo.LayoutInfo.Line)); } }
Der Fehler hängt mit dem
erneuten Aufrufen von
OrderBy für eine Auflistung vom Typ
IOrderedEnumerable zusammen . Hier wird die Sammlung zuerst nach Spalten und dann nach Zeilen sortiert. Darüber hinaus wird zum Zeitpunkt der Sortierung nach Zeilen die vorherige Sortierung nach Spalten nirgendwo berücksichtigt. Verwenden Sie
ThenBy , um die Sortierung nach Spalten nicht zu verlieren und die Sammlung nach mehreren Kriterien gleichzeitig zu
sortieren :
this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line));
PVS-Studio Warnung :
V3008 Der Variablen 'currentColumnLength' werden zweimal hintereinander Werte zugewiesen. Vielleicht ist das ein Fehler. Überprüfen Sie die Zeilen: 791, 785. WrapLayout.cs 791
private void OnAvailableLengthChanged(double oldValue, double newValue) { .... if (....) { if (currentColumnLength > 0) { var paddingValue = Math.Max(0, newValue - currentColumnLength); this.paddingRenderInfo.Add(paddingValue); currentColumnLength = 0;
Dem Analysator erschien es verdächtig, dass der Variablen
currentColumnLength zweimal ein Wert zugewiesen wurde. Die Variable wird nicht zwischen Zuweisungen verwendet. Unabhängig von der Bedingung ist diese Variable letztendlich Null. Dieser Code ist entweder falsch oder redundant.
PVS-Studio Warnung :
V3127 Es wurden zwei ähnliche Codefragmente gefunden. Möglicherweise handelt es sich um einen Tippfehler, und anstelle von RadRatingItem.cs 240 sollte die Variable 'emptyIconContainer' verwendet werden
public class RadRatingItem : RadContentControl { .... protected override void OnApplyTemplate() { .... this.filledIconContainer = this.GetTemplateChild( "FilledIconContainer") as Border; if (this.filledIconContainer == null)
Aufgrund eines Tippfehlers wurden im Code zwei identische Bedingungen angezeigt. Gemessen an der generierten Ausnahme sollte die zweite Bedingung folgendermaßen aussehen:
if (this.emptyIconContainer == null) { throw new MissingTemplatePartException( "EmptyIconContainer", typeof(Border)); }
PVS-Studio Warnung :
V3020 Eine bedingungslose Unterbrechung innerhalb einer Schleife. NodePool.cs 189
public IEnumerable<KeyValuePair<int, List<T>>> GetUnfrozenDisplayedElements() { foreach (var item in this.generatedContainers) { foreach (var pair in item.Value) { if (!pair.IsFrozen) { yield return item; } break; } } }
Der Analysator stellte fest, dass hier die
break- Anweisung nicht zur
if-Anweisung gehört .
Break wird unabhängig vom Wert von
pair.IsFrozen ausgeführt.
Aus diesem Grund wird in
foreach nur eine Iteration ausgeführt.
Damit ist meine Überlegung zu Warnungen abgeschlossen. Damit Telerik-Entwickler eine gründlichere Code-Analyse durchführen und Fehler beheben können, sind wir bereit, ihnen eine temporäre Lizenz zur Verfügung zu stellen. Darüber hinaus können sie die
kostenlose Nutzung der PVS-Studio- Option nutzen, die Autoren von Open Source-Projekten zur Verfügung gestellt wird.
Fazit
Obwohl die Entwickler von Telerik UI für UWP großartige Arbeit geleistet haben, war es nicht ohne Tippfehler, wie es normalerweise passiert :). Alle diese Fehler konnten leicht von einem statischen Analysegerät gefunden und korrigiert werden. Das Wichtigste ist, den Analysator
korrekt und regelmäßig zu verwenden .

Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Ekaterina Nikiforova.
Überprüfen der Telerik-Benutzeroberfläche auf UWP als Einstieg in PVS-Studio .