Periksa Telerik UI untuk UWP untuk berkenalan dengan PVS-Studio

Gambar 2

Sudah menjadi tradisi bahwa pemrogram mengisi tim PVS-Studio memulai pekerjaan mereka dengan menulis artikel tentang menganalisis proyek sumber terbuka. Kali ini, proyek yang terbukti seperti itu adalah Telerik UI untuk UWP.

Penganalisa kode PVS-Studio


PVS-Studio adalah alat untuk mendeteksi kesalahan dan kerentanan potensial dalam kode sumber program yang ditulis dalam C, C ++, C # dan Java. Berjalan di Windows, Linux, dan macOS.

Penganalisis menyediakan berbagai skenario penggunaan:

  • dapat digunakan secara lokal pada mesin pengembangan, terintegrasi sebagai plug-in dengan Visual Studio atau IntelliJ IDEA;
  • dapat berintegrasi dengan platform jaminan kualitas berkelanjutan SonarQube;
  • dapat digunakan secara independen, diintegrasikan ke dalam sistem perakitan;
  • dimungkinkan untuk menggunakan utilitas pemantauan kompilasi;
  • integrasi dengan Azure DevOps, Jenkins, TeamCity, Travis CI dan sistem serupa dimungkinkan;
  • dan sebagainya.

Proyek yang Diaudit


Telerik UI untuk UWP adalah seperangkat komponen antarmuka pengguna untuk Universal Windows Platform (UWP). Kode sumber untuk proyek dapat ditemukan di Github . Set ini mencakup lebih dari 20 komponen yang memungkinkan Anda untuk memvisualisasikan data dalam bentuk grafik, membuat daftar dan tabel, menggunakan peta untuk menampilkan data yang terkait dengan lokasi.

Fragmen yang menarik perhatian saat mempelajari laporan penganalisa


Peringatan PVS-Studio : V3013 Aneh bahwa tubuh fungsi 'OnMinValuePropertyChanged' sepenuhnya setara dengan tubuh fungsi 'OnMaxValuePropertyChanged'. 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); } } } 

Penganalisa mendeteksi dua metode, OnMinValuePropertyChanged dan OnMaxValuePropertyChanged , yang melakukan tindakan yang sama. Saya memiliki kecurigaan kuat bahwa kesalahan telah merayap ke dalam kode ini. Perhatikan bahwa metode OnMinValuePropertyChanged dan metode OnMaxValuePropertyChanged menggunakan RaiseMinimumPropertyChangedEvent . Pada saat yang sama, di kelas RadGaugeAutomationPeer Anda dapat menemukan metode untuk "Minimum" dan untuk "Maksimum":

 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); } 

Metode RaiseMaximumPropertyChangedEvent tidak pernah digunakan dalam kode, tetapi RaiseMinimumPropertyChangedEvent digunakan dua kali. Dan, Anda tahu, kinerja metode OnMaxValuePropertyChanged menimbulkan pertanyaan ... Saya pikir seharusnya menulis yang berikut ini:

 private static void OnMaxValuePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args) { .... peer.RaiseMaximumPropertyChangedEvent((double)args.OldValue, (double)args.NewValue); .... } 

Namun demikian, kode tersebut tidak terlihat sangat rapi karena banyaknya elemen berulang. Sulit untuk dipahami, dan kalimat yang berulang-ulang menumpulkan perhatian programmer, dan menjadi lebih sulit untuk melakukan tinjauan kode dalam kondisi seperti itu. Tetapi alat analisis statis melakukan pekerjaan yang sangat baik untuk memeriksa kode tersebut (tetapi ini tidak berarti bahwa Anda dapat melakukannya tanpa refactoring dan terutama tanpa mengurangi jumlah baris yang diulang).

Dari cuplikan kode di atas dan di bawah ini, kita dapat mengasumsikan bahwa penulis tidak menolak untuk menyalin-menempel. Namun, seperti kita semua ... :)

Peringatan PVS-Studio : V3001 Ada elemen sub-ekspresi yang identik.RenderSize == emptySize 'ke kiri dan ke kanan' || ' operator. 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); } 

Penganalisis mendeteksi fragmen kode kesalahan di mana ke kanan dan ke kiri operator '||' pernyataan if menggunakan subekspresi yang sama. Subekspresi kedua jelas terlihat berbeda. Mungkin menggantikan RenderSize kedua yang harus DiinginkanSize . Atau seharusnya tidak ada subekspresi kedua sama sekali. Bagaimanapun, potongan kode ini perlu diperbaiki.

Peringatan PVS-Studio : V3001 Ada sub-ekspresi yang identik 'teks [0] ==' - '' di sebelah kiri dan di sebelah kanan '||' operator. 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; } .... } 

Di sini, pengembang menulis teks yang dimasukkan dalam bidang kotak teks ke variabel. Kemudian karakter pertama dari string dibandingkan dua kali dengan karakter yang sama '-', yang merupakan keputusan yang mencurigakan. Jelas, validasi teks dalam fungsi ini tidak berfungsi seperti yang dimaksudkan semula.

Peringatan PVS-Studio : V3001 Ada sub-ekspresi 'newValue.HasValue' yang identik di sebelah kiri dan di sebelah kanan operator '&&'. 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) // <= .... } 

Ekspresi newValue.HasValue mengembalikan true jika newValue berisi nilai apa pun, dan ekspresi newValue! = Null melakukan hal yang sama. Penganalisa memperhatikan hal ini, dan apa yang harus dilakukan adalah menghapus salah satu dari subekspresi atau menggantinya dengan yang lain (jika sesuatu yang lain harus diperiksa), tergantung pada keputusan pengembang.

Peringatan PVS-Studio : V3125 Objek 'CurrentAttachedMenu' digunakan setelah diverifikasi terhadap nol. Periksa baris: 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(); } } } 

Jika variabel CurrentAttachedMenu berubah menjadi nol , maka evaluasi ekspresi CurrentAttachedMenu.IsOpen akan memunculkan exception. Pada pandangan pertama, tampaknya ini adalah salah ketik yang sederhana dan tidak berarti perbandingan dengan nol , tetapi operasi terbalik - '! ='. Tapi kemudian pengecualian akan terjadi dalam kondisi pernyataan if jika variabel CurrentAttachedMenu adalah nol .

Lebih lanjut dalam kode ada 37 peringatan lain yang sama, beberapa di antaranya tampaknya menunjukkan kesalahan. Tetapi untuk menggambarkannya dalam kerangka satu artikel masih terlalu banyak, jadi saya akan membiarkannya tanpa pengawasan.

Peringatan PVS-Studio : V3019 Kemungkinan variabel yang salah dibandingkan dengan nol setelah konversi jenis menggunakan kata kunci 'sebagai'. Periksa variabel '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; } .... } 

Sangat mungkin bahwa penulis mencampur variabel. Ketidaksetaraan nol diperiksa bukan oleh tautan yang diperoleh sebagai hasil pemeran, tetapi oleh yang asli ( dragDropElement ). Kemungkinan besar, tautan uiDragDropElement seharusnya diperiksa . Dugaan ini juga dikonfirmasi oleh fakta bahwa programmer selanjutnya menggunakan uiDragDropElement tanpa memeriksa nol .

Peringatan PVS-Studio : V3030 Pemeriksaan berulang. Kondisi '! ShowIndicatorWhenNoData' sudah diverifikasi di baris 139. 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; } .... } 

Penganalisa menemukan sepotong kode di mana, di bawah dua kondisi, variabel showIndicatorWhenNoData yang sama diperiksa ulang. Mungkin cek itu hanya mubazir, tetapi ada juga kemungkinan bahwa salah satu subekspresi duplikat harus berbeda sama sekali.

Peringatan PVS-Studio : V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' Operator dikelilingi oleh ekspresi yang berlawanan. 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); } } 

Potongan kode ini tidak salah secara formal. Alat analisa mengisyaratkan beberapa kode redundansi dalam kondisi tersebut. Namun, perlu diingat bahwa kode tambahan kadang-kadang merupakan hasil dari kesalahan, misalnya, ketika alih-alih satu variabel, yang lain diperiksa beberapa kali.

Anda dapat sedikit mengurangi kondisi ini dan menghapus kode tambahan. Misalnya, seperti ini:

 internal class SelectedItemCollection : ObservableCollection<object> { .... private bool CanInsertItem(object item) { return this.suspendLevel == 0 && this.AllowSelect && (this.AllowMultipleSelect || this.Count == 0); } } 

Pesan serupa lainnya:

  • V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' Operator dikelilingi oleh ekspresi yang berlawanan. SelectedItemCollection.cs 93
  • V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' Operator dikelilingi oleh ekspresi yang berlawanan. StackVirtualizationStrategy.cs 49
  • V3031 Pemeriksaan berlebihan dapat disederhanakan. '||' operator dikelilingi oleh ekspresi berlawanan 'state == null' dan 'state! = null'. LocalFieldDescriptionProviderBase.cs 24

Pertimbangkan potongan kode lain di mana penganalisis mengembalikan yang berikut:

Peringatan PVS-Studio :

  • V3137 Variabel 'leftMargin' ditugaskan tetapi tidak digunakan pada akhir fungsi. DragDrop.cs 87
  • V3137 Variabel 'topMargin' diberikan tetapi tidak digunakan pada akhir fungsi. DragDrop.cs 88

 internal static class DragDrop { .... double leftMargin = 0d; double topMargin = 0d; if (frameworkElementSource != null) { leftMargin = frameworkElementSource.Margin.Left; // <= topMargin = frameworkElementSource.Margin.Top; // <= } if (dragDropElement == null || !dragDropElement.CanStartDrag(trigger, initializeContext)) { return; } var context = dragDropElement .DragStarting(trigger, initializeContext); if (context == null) { return; } var startDragPosition = e .GetCurrentPoint(context.DragSurface.RootElement).Position; var relativeStartDragPosition = e .GetCurrentPoint(uiDragDropElement).Position; var dragPositionMode = DragDrop .GetDragPositionMode(uiDragDropElement); AddOperation(new DragDropOperation( context, dragDropElement, dragPositionMode, e.Pointer, startDragPosition, relativeStartDragPosition)); } 

Penganalisa melaporkan bahwa variabel leftMargin dan topMargin telah diberi nilai, tetapi setelah itu variabel-variabel ini tidak digunakan sampai akhir metode. Mungkin tidak ada kesalahan di sini, tetapi kode tersebut terlihat mencurigakan. Ini mungkin karena kesalahan ketik atau refactoring yang gagal.

Masalah yang sama ditemukan di tempat lain: V3137 Variabel 'currentColumnLength' ditugaskan tetapi tidak digunakan pada akhir fungsi. WrapLayout.cs 824

Peringatan PVS-Studio : V3061 Parameter 'indeks' selalu ditulis ulang dalam tubuh metode sebelum digunakan. 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, // <= valueProvider.GetSortComparer()); return Tuple.Create(aggregateRowGroup, index); } } 

Parameter indeks metode FindGroupAndItemIndex ditimpa sebelum digunakan. Kemungkinan besar, ini menunjukkan kesalahan programmer.

Peringatan PVS-Studio : V3083 Doa yang tidak aman dari acara 'Selesai', NullReferenceException dimungkinkan. Pertimbangkan menugaskan acara ke variabel lokal sebelum menjalankannya. ActionBase.cs 32

 internal abstract class ActionBase { .... protected virtual void OnCompleted() { this.IsCompleted = true; if (this.Completed != null) { this.Completed(this, EventArgs.Empty); } } } 

Programmer memungkinkan panggilan yang berpotensi tidak aman ke event handler dalam metode ini, yang dapat menyebabkan pengecualian tipe NullReferenceException . Pengecualian akan diberikan asalkan antara cek nol dan panggilan penangan acara, acara ini tidak tetap.

Ada 49 masalah serupa lainnya dalam kode. Tidak akan menarik untuk menonton semuanya di artikel ini, dan penulis akan dapat dengan mudah menemukannya sendiri menggunakan PVS-Studio, jadi kami akan beralih ke kesalahan lain.

PVS-Studio Warning : V3145 Dereference tidak aman dari target WeakReference, pertimbangkan untuk memeriksa info. Target. Objek tersebut bisa berupa sampah yang dikumpulkan antara memeriksa 'IsAlive' dan mengakses properti 'Target'. FadeAnimation.cs 84

 public class RadFadeAnimation : RadAnimation { .... protected internal override void ApplyAnimationValues(PlayAnimationInfo info) { .... if (info.Target.Opacity != opacity) // <= { info.Target.Opacity = opacity; } .... } .... } 

Penganalisis memperingatkan tentang bahaya pengecualian tipe NullReferenceException saat mengakses properti info.Target.Opacity . Untuk lebih memahami esensi masalah, Anda perlu melihat fragmen kelas PlayAnimationInfo , khususnya, properti Target .

 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; } } .... } 

Secara umum, semakin jauh Anda menggali kode ini, semakin banyak masalah potensial yang dapat Anda temukan di dalamnya. Mari kita lihat mungkin yang paling menarik - yang mana analis mengeluarkan peringatan. Faktanya adalah bahwa bahkan jika eksekusi mengikuti cabang kemudian dari pernyataan if , ini tidak menjamin bahwa referensi yang tidak nol akan dikembalikan. Terlepas dari percakapan tentang para pemeran, di sini kami menganggap segala sesuatu diizinkan karena inisialisasi objek dalam konstruktor.

Bagaimana ini mungkin? Faktanya adalah bahwa jika antara cek IsAlive dan Panggilan target pengumpulan sampah dilakukan, di mana objek yang dirujuk oleh WeakReference jatuh , this.target.Target akan mengembalikan nol . Yaitu, pemeriksaan IsAlive tidak menjamin bahwa pada saat Target diakses, objek masih tersedia.

Omong-omong, situasinya kembali nol; menangkap aturan diagnostik lain: V3080 Kemungkinan null dereference. Pertimbangkan untuk memeriksa 'info.Target'. FadeAnimation.cs 84

Masalah serupa dalam kode terjadi beberapa kali lagi:

  • V3145 dereference tidak aman dari target WeakReference, pertimbangkan memeriksa target. Objek tersebut dapat berupa sampah yang dikumpulkan sebelum properti 'Target' diakses. MoveXAnimation.cs 80
  • V3145 dereference tidak aman dari target WeakReference, pertimbangkan memeriksa target. Objek tersebut dapat berupa sampah yang dikumpulkan sebelum properti 'Target' diakses. MoveYAnimation.cs 80
  • V3145 Dereferensi tidak aman dari target WeakReference, pertimbangkan untuk memeriksa info. Target. Objek tersebut dapat berupa sampah yang dikumpulkan sebelum properti 'Target' diakses. PlaneProjectionAnimation.cs 244
  • V3145 Dereferensi tidak aman dari target WeakReference. Objek tersebut bisa berupa sampah yang dikumpulkan antara memeriksa 'IsAlive' dan mengakses properti 'Target'. WeakEventHandler.cs 109

Mari kita beralih ke contoh berikut.

Peringatan PVS-Studio : V3066 Kemungkinan urutan argumen yang salah diteruskan ke 'NotifyCollectionChangedEventArgs' konstruktor: 'oldItem' dan '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); // <= default: return new NotifyCollectionChangedEventArgs(action); } } } 

Untuk memahami apa arti peringatan ini dari penganalisa, perlu melihat parameter konstruktor NotifyCollectionChangedEventArgs :

  public NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction action, object newItem, object oldItem, int index); 

Penganalisa memperingatkan bahwa dalam ungkapan
  return new NotifyCollectionChangedEventArgs( action, oldItem, newItem, changeIndex); 

menukar variabel oldItem dan newItem . Dalam definisi konstruktor, mereka terdaftar dalam urutan yang berbeda. Apakah ini dilakukan secara sadar atau tidak, orang hanya bisa menebak.

PVS-Studio Warning : V3102 Akses mencurigakan ke elemen objek 'x' dengan indeks konstan di dalam satu loop. 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])) // <= { return false; } } return true; } .... } 

Pada setiap iterasi dalam loop, programmer membandingkan x [0] dan y [0]. Namun, loop tidak masuk akal dalam kode ini, karena hanya elemen pertama yang dibandingkan. Kemungkinan besar, ini berarti membandingkan elemen array yang sesuai. Maka kode yang benar akan seperti ini:

 for (int i = 0; i < x.Length; i++) { if (!object.Equals(x[i], y[i])) { return false; } } 

Peringatan PVS-Studio : V3123 Mungkin operator '?:' Bekerja dengan cara yang berbeda dari yang diharapkan. Prioritasnya lebih rendah daripada prioritas operator lain dalam kondisinya. EditRowHostPanel.cs 35

 protected override Size MeasureOverride(Size availableSize) { .... bool shouldUpdateRowHeight = editorLine == 0 || displayedElement == null ? false : displayedElement.ContainerType != typeof(DataGridGroupHeader); .... } 

Peringatan dikaitkan dengan penggunaan Operator '?:'. Ini memiliki prioritas lebih rendah daripada ! =, ||, ==. Oleh karena itu, ekspresi tidak dapat dievaluasi sesuai yang direncanakan oleh programmer. Rupanya, dalam hal ini ini adalah false positive dan kode berfungsi dengan benar. Tetapi membaca kode seperti itu sangat sulit dan tidak pernah ada kepastian bahwa itu dipahami dengan benar. Rasanya seperti pengembang menulis sedemikian rupa sehingga tidak ada yang mengerti apa-apa :) Cara terbaik untuk melakukan ini lebih mudah dibaca - gunakan tanda kurung atau pernyataan if .

PVS-Studio Warning : V3078 Order sorting orisinal akan hilang setelah panggilan berulang ke metode 'OrderBy'. Gunakan metode 'ThenBy' untuk mempertahankan penyortiran asli. 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)); } } 

Kesalahan terkait dengan memanggil OrderBy lagi untuk koleksi tipe IOrderedEnumerable . Di sini koleksi diurutkan terlebih dahulu oleh kolom, lalu oleh baris. Selain itu, pada saat mengurutkan berdasarkan baris, pengurutan sebelumnya berdasarkan kolom tidak diperhitungkan di mana pun. Agar tidak kehilangan pengurutan menurut kolom dan mengurutkan koleksi berdasarkan beberapa kriteria sekaligus, maka gunakan ThenBy :

  this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line)); 

PVS-Studio Warning : V3008 Variabel 'currentColumnLength' diberi nilai dua kali berturut-turut. Mungkin ini sebuah kesalahan. Periksa baris: 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; // <= slotCount++; } this.ColumnSlotsRenderInfo.Update(i, newValue); this.paddingRenderInfo.Add(0); currentColumnLength = 0; // <= slotCount++; continue; } else { .... } .... } 

Tampaknya mencurigakan bagi penganalisa bahwa variabel currentColumnLength diberi nilai dua kali. Variabel tidak digunakan di antara tugas. Terlepas dari kondisinya, variabel ini pada akhirnya akan menjadi nol. Kode ini salah atau berlebihan.

Peringatan PVS-Studio : V3127 Ditemukan dua fragmen kode serupa. Mungkin, ini adalah salah ketik dan variabel 'emptyIconContainer' harus digunakan sebagai ganti 'filledIconContainer' RadRatingItem.cs 240

 public class RadRatingItem : RadContentControl { .... protected override void OnApplyTemplate() { .... this.filledIconContainer = this.GetTemplateChild( "FilledIconContainer") as Border; if (this.filledIconContainer == null) // <= { throw new MissingTemplatePartException( "FilledIconContainer", typeof(Border)); } this.emptyIconContainer = this.GetTemplateChild( "EmptyIconContainer") as Border; if (this.filledIconContainer == null) // <= { throw new MissingTemplatePartException( "EmptyIconContainer", typeof(Border)); } this.Initialize(); } .... } 

Karena kesalahan ketik, dua kondisi identik muncul dalam kode. Dilihat dari pengecualian yang dihasilkan, kondisi kedua akan terlihat seperti ini:

 if (this.emptyIconContainer == null) { throw new MissingTemplatePartException( "EmptyIconContainer", typeof(Border)); } 

PVS-Studio Warning : V3020 'break' tanpa syarat dalam satu loop. 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; } } } 

Penganalisa menemukan bahwa di sini pernyataan break bukan milik pernyataan if . Break akan dieksekusi terlepas dari nilai pair.IsFrozen dan karena ini dalam foreach , hanya satu iterasi yang akan dilakukan.

Itu menyimpulkan pertimbangan saya akan peringatan. Agar pengembang Telerik dapat melakukan analisis kode yang lebih teliti dan memperbaiki cacat, kami siap memberi mereka lisensi sementara. Selain itu, mereka dapat mengambil keuntungan dari penggunaan bebas opsi PVS-Studio yang diberikan kepada penulis proyek sumber terbuka.

Kesimpulan


Meskipun pengembang Telerik UI untuk UWP melakukan pekerjaan dengan baik, itu bukan tanpa kesalahan ketik, seperti yang biasanya terjadi :). Semua kesalahan ini dapat dengan mudah ditemukan oleh penganalisa statis dan diperbaiki. Yang paling penting adalah menggunakan penganalisis dengan benar dan teratur .



Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Ekaterina Nikiforova. Memeriksa Telerik UI untuk UWP sebagai Cara Memulai dengan PVS-Studio .

Source: https://habr.com/ru/post/id470584/


All Articles