Laporan tercepat di barat liar. Dan beberapa bug di samping ...

Gambar 3

Microsoft tidak hanya baru-baru ini memposting kode sumber terbuka dari proyeknya sendiri - perusahaan lain juga mengikuti tren ini. Bagi kami, pengembang PVS-Studio, ini adalah cara yang bagus untuk menguji penganalisa lagi, melihat hal-hal menarik apa yang dapat ditemukan, dan memberi tahu penulis proyek tentang hal itu. Hari ini kita melihat ke dalam proyek Laporan Cepat.

Apa yang diperiksa?


FastReport adalah generator laporan yang dikembangkan oleh Fast Reports . Ditulis dalam C # dan kompatibel dengan .NET Standard 2.0+. Kode sumber proyek baru-baru ini diposting di GitHub , di mana ia diunduh untuk analisis lebih lanjut.

Laporan mendukung penggunaan teks, gambar, garis, bentuk, diagram, tabel, barcode, dll. Laporan dapat berupa halaman tunggal dan multi halaman, termasuk berisi, selain data, sampul dan halaman belakang. Sumber data dapat berupa XML, CSV, Json, MS SQL, MySql, Oracle, Postgres, MongoDB, Couchbase, RavenDB, SQLite.

Ada berbagai cara untuk membuat templat laporan: dari kode; sebagai file xml; menggunakan desainer online atau FastReport Designer Community Edition.

Jika perlu, perpustakaan dapat diunduh sebagai paket NuGet .

Anda dapat membaca lebih lanjut tentang fitur produk di halaman GitHub proyek .

Gambar 8


Tidak ada masalah dengan perakitan proyek - saya mengumpulkannya dari Visual Studio 2017, dari mana kemudian diperiksa oleh plugin PVS-Studio.

PVS-Studio adalah penganalisa statis yang mencari kesalahan dalam C, C ++, C #, kode Java. Saat menganalisis kode C #, Anda dapat menggunakan penganalisa IDE Visual Studio menggunakan plug-in PVS-Studio, atau Anda dapat memeriksa proyek dari baris perintah , di mana utilitas baris perintah PVS-Studio_Cmd.exe digunakan. Jika mau, Anda dapat mengonfigurasi analisis pada server build atau menghubungkan hasil analisis ke SonarQube .

Baiklah, mari kita lihat apa yang menarik kali ini.

Karena proyek ini kecil, Anda tidak boleh mengandalkan banyak kesalahan ketik dan tempat mencurigakan. Mari kita lihat apa yang ditemukan, dan bahkan mencoba mereproduksi sesuatu dalam praktik.

Kacamata dan lainnya


Temui metode berikut:

public override string ToString() { if (_value == null) return null; return this.String; } 

Peringatan PVS-Studio : V3108 Tidak disarankan untuk mengembalikan 'null' dari metode 'ToSting ()'. Variant.cs 1519

Ya, mengembalikan null dari metode ToString () yang diganti bukan kesalahan sendiri, tetapi tetap saja gaya yang buruk. Ini ditunjukkan, antara lain, dalam dokumentasi dari Microsoft : Override ToString () Anda seharusnya tidak mengembalikan string kosong atau null . Pengembang yang tidak mengharapkan pengembalian nol sebagai nilai pengembalian ToString () mungkin terkejut ketika sebuah ArgumentNullException dilempar selama pelaksanaan kode di bawah ini (asalkan metode ekstensi dipanggil untuk IEnumerable <T> ).

 Variant varObj = new Variant(); varObj.ToString().Contains(character); 

Anda dapat menemukan kesalahan dengan fakta bahwa contohnya adalah sintetis, tetapi esensi dari ini tidak berubah.

Selain itu, kode ini dikomentari sebagai berikut:

 /// <summary> /// Returns <see cref="String"/> property unless the value on the right /// is null. If the value on the right is null, returns "". /// </summary> /// <returns></returns> 

Ups Alih-alih mengembalikan "" null .

Mari kita lanjutkan.

Ada kelas FastString di perpustakaan . Deskripsi: Alternatif cepat dari StringBuilder . Sebenarnya, kelas ini berisi bidang tipe StringBuilder . Konstruktor dari kelas FastString memanggil metode Init , yang menginisialisasi bidang yang sesuai.

Kode salah satu konstruktor:

 public FastString() { Init(initCapacity); } 

Dan kode metode Init :

 private void Init(int iniCapacity) { sb = new StringBuilder(iniCapacity); //chars = new char[iniCapacity]; //capacity = iniCapacity; } 

Jika diinginkan, Anda dapat mengakses bidang sb melalui properti StringBuilder :

 public StringBuilder StringBuilder { get { return sb; } } 

Secara total, FastString memiliki 3 konstruktor:

 public FastString(); public FastString(int iniCapacity); public FastString(string initValue); 

Saya sudah menunjukkan tubuh perancang pertama bahwa mereka membuat dua tebakan yang tersisa, saya pikir, juga tidak sulit. Dan sekarang, perhatian. Coba tebak apa yang akan dihasilkan oleh kode berikut:

 FastString fs = new FastString(256); Console.WriteLine(fs.StringBuilder.Capacity); 

Perhatian, jawabannya:

Gambar 2


Tanpa diduga? Mari kita lihat tubuh konstruktor yang sesuai:

 public FastString(int iniCapacity) { Init(initCapacity); } 

Pembaca reguler dari artikel kami harus sudah memiliki perhatian untuk menemukan masalah di sini. Penganalisa mata (aroma, logika, sebut saja apa yang Anda inginkan) pasti mati rasa, dan ia menemukan masalah: V3117 Parameter konstruktor 'iniCapacity' tidak digunakan. FastString.cs 434

Suatu kebetulan bahwa kode kelas berisi bidang initCapacity yang konstan, yang dilewatkan sebagai argumen ke metode Init alih-alih parameter konstruktor iniCapacity ...

 private const int initCapacity = 32; 

Saat menggunakan nama yang mirip, Anda harus sangat, sangat berhati-hati. Di mana pun kesalahan dibuat terkait dengan penggunaan nama yang serupa - proyek di C, C ++, C #, Jawa - ada kesalahan ketik di mana-mana ...

By the way, tentang kesalahan ketik.

Mari kita buat contoh sederhana berikut dan lihat cara kerjanya:

 static void Main(string[] args) { TextObject textObj = new TextObject(); textObj.ParagraphFormat = null; Console.WriteLine("Ok"); } 

Seperti yang sudah Anda tebak, output akan berbeda dari string "Oke" :)

Yang mana Jadi misalnya:

Gambar 1


Masalahnya terletak pada properti ParagraphFormat dan dalam menggunakan nama yang serupa:

 public ParagraphFormat ParagraphFormat { get { return paragraphFormat; } set { ParagraphFormat = value; } } 

Peringatan PVS-Studio : V3110 Kemungkinan rekursi tak terbatas di dalam properti 'ParagraphFormat'. TextObject.cs 281

Properti ParagraphFormat adalah pembungkus di atas bidang paragraphFormat . Selain itu, accessor properti get-nya dieja dengan benar, tetapi set accessor properti berisi kesalahan ketik yang mengganggu: alih-alih bidang, catatan terjadi di properti yang sama, yang menyebabkan rekursi. Sekali lagi, kesalahan terkait dengan nama yang mirip.

Pertimbangkan potongan kode berikut.

 public override Run Split(float availableWidth, out Run secondPart) { .... if (r.Width > availableWidth) { List<CharWithIndex> list = new List<CharWithIndex>(); for (int i = point; i < size; i++) list.Add(chars[i]); secondPart = new RunText(renderer, word, style, list, left + r.Width, charIndex); list.Clear(); for (int i = 0; i < point; i++) list.Add(chars[i]); r = new RunText(renderer, word, style, list, left, charIndex); return r; } else { List<CharWithIndex> list = new List<CharWithIndex>(); for (int i = point; i < size; i++) list.Add(chars[i]); secondPart = new RunText(renderer, word, style, list, left + r.Width, charIndex); list.Clear(); for (int i = 0; i < point; i++) list.Add(chars[i]); r = new RunText(renderer, word, style, list, left, charIndex); return r; } .... } 

PVS-Studio Warning : V3004 Pernyataan 'then' setara dengan pernyataan 'else'. HtmlTextRenderer.cs 2092

Sedikit salin-tempel, dan sekarang, terlepas dari nilai ekspresi r. Lebar> tersedia Lebar , tindakan yang sama akan dilakukan. Hapus pernyataan if atau ubah logika di salah satu cabang.

 public static string GetExpression(FindTextArgs args, bool skipStrings) { while (args.StartIndex < args.Text.Length) { if (!FindMatchingBrackets(args, skipStrings)) break; return args.FoundText; } return ""; } 

Peringatan Analyzer : V3020 'pengembalian' tanpa syarat dalam satu lingkaran. CodeUtils.cs 262

Karena pernyataan pengembalian tanpa syarat , tidak lebih dari satu iterasi akan dieksekusi untuk loop di atas. Mungkin kode ini ternyata setelah refactoring, atau mungkin itu hanya cara yang tidak biasa untuk melakukan apa yang bisa dilakukan tanpa loop.

 private int FindBarItem(string c) { for (int i = 0; i < tabelle_cb.Length; i++) { if (c == tabelle_cb[i].c) return i; } return -1; } internal override string GetPattern() { string result = tabelle_cb[FindBarItem("A")].data + "0"; foreach (char c in text) { int idx = FindBarItem(c.ToString()); result += tabelle_cb[idx].data + "0"; } result += tabelle_cb[FindBarItem("B")].data; return result; } 

Peringatan PVS-Studio : V3106 Nilai indeks negatif yang mungkin. Nilai indeks 'idx' bisa mencapai -1. BarcodeCodabar.cs 70

Kode yang berpotensi berbahaya. Metode FindBarItem dapat mengembalikan -1 jika tidak menemukan elemen yang dilewatkan sebagai parameter. Dalam kode panggilan (metode GetPattern ), nilai ini ditulis ke variabel idx dan digunakan sebagai indeks array tabelle_cb tanpa verifikasi awal. Saat mengakses indeks -1, pengecualian tipe IndexOutOfRangeException akan dibuang .

Mari kita lanjutkan.

 protected override void Finish() { .... if (saveStreams) { FinishSaveStreams(); } else { if (singlePage) { if (saveStreams) { int fileIndex = GeneratedFiles.IndexOf(singlePageFileName); DoPageEnd(generatedStreams[fileIndex]); } else { .... } .... } .... } .... } 

Peringatan PVS-Studio : Ekspresi V3022 'saveStreams' selalu salah. HTMLExport.cs 849

Kode di atas dengan mendapatkan nilai fileIndex dan memanggil metode DoPageEnd tidak akan pernah dieksekusi, karena hasil dari ekspresi saveStreams kedua dalam kode akan selalu salah .

Yang paling menarik, mungkin ini semua (Anda tidak mengharapkan artikel dalam semangat analisis Mono ?). Ada peringatan penganalisa lain, tetapi mereka tampaknya tidak cukup menarik bagi saya untuk memasukkannya dalam artikel (bagian selalu tertinggal di belakang layar).

Mengetahui desain akan berguna untuk analisis mereka, jadi idealnya, penulis harus melihat peringatan ini sendiri. Ini adalah peringatan seperti V3083 (panggilan yang berpotensi berbahaya untuk penangan acara), V3022 (kondisi selalu benar / salah (dalam hal ini, seringkali karena metode yang mengembalikan nilai tunggal)), V3072 , V3073 (bekerja dengan IDisposable ) dan lainnya.

Jika semua ini tidak relevan, Anda dapat:


Kesimpulan


Gambar 4


Terlepas dari kenyataan bahwa artikel itu pendek, saya senang untuk 'menyentuh' peringatan penganalisa dengan tangan saya - untuk melihat bagaimana apa yang disumpah oleh penganalisa dalam praktiknya.

Saya berharap penulis proyek berhasil, koreksi masalah yang ditemukan, dan saya ingin memuji satu langkah menuju komunitas open-source!

Saya menyarankan sisanya untuk mencoba analisa pada kode Anda dan melihat apa yang menurut Anda menarik.

Semua yang terbaik!



Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Sergey Vasiliev. Laporan Tercepat di Wild West - dan Segenggam Bug ...

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


All Articles