Sebagian galat terlihat tanpa menjalankan program: variabel yang diisi tetapi tidak pernah dibaca, nama yang menimpa fungsi bawaan, array yang tumbuh di dalam loop, atau kode setelah return yang tak pernah tercapai. Code analysis (analisis statis) memindai berkas .m dan melaporkan pola berisiko tersebut sebelum satu baris pun dieksekusi. Chapter ini membahas checkcode beserta linter manual:

  • Menjalankan checkcode dan membaca keluarannya (termasuk ID pesan seperti NASGU).
  • Kategori temuan umum dan cara memperbaikinya.
  • Integrasi ke alur kerja: Editor, Code Analyzer App, dan CI.
  • Padanan manual berbasis regexp yang teruji di Octave.

checkcode: Linter di Command Window #

Fungsi checkcode(filename) memindai berkas .m dan menampilkan pesan berformat L <baris> (C <kolom>): <pesan>. Bentuk terpentingnya tiga: tampilan langsung, struct untuk pemrosesan (-struct), dan struct plus ID pesan (-id):

matlab
% Sumber: dokumentasi resmi MATLAB (MATLAB-ONLY)
checkcode('lengthofline.m')
info = checkcode('lengthofline.m', '-id')

Contoh keluaran dari dokumentasi resmi (berkas contoh lengthofline.m):

text
L 21 (C 1-9): Value assigned to variable might be unused.
L 22 (C 12-15): NUMEL(x) is usually faster than PROD(SIZE(x)).
L 23 (C 5-11): Variable appears to change size on every loop iteration.

Dengan opsi -id, struct keluaran memuat field id, message, fix, line, dan column. Pesan pertama contoh resmi ber-ID NASGU (“value assigned but never used”). Opsi lain yang berguna: -cyc/-modcyc (kompleksitas siklomatik per fungsi), -notok (tetap periksa baris ber-pragma %#ok), dan -fullpath. Sejak R2022b MATLAB merekomendasikan codeIssues sebagai pengganti interaktif checkcode — keduanya memakai mesin analisis yang sama.

Kategori Temuan Umum #

Code Analyzer mengelompokan temuan berdasarkan ID. Kategori yang paling sering muncul dalam kode nyata:

KategoriID tipikContohPerbaikan
Variabel tak terpakaiNASGUpajak = 0.1; tak pernah dibacahapus baris atau gunakan nilainya
Menimpa fungsi bawaan(shadowing)size = 3; menutup size()ganti nama variabel
Array tumbuh dalam loopAGROWhasil = [hasil, x]; di forprealokasi zeros()
Kode tak terjangkau—pernyataan setelah returnhapus
Inefisiensi gaya lamaPRTPLS dll.PROD(SIZE(x)) vs NUMEL(x)ganti idiom modern
Input belum diverifikasi—argumen tak diperiksavalidasi di awal (chapter Error Handling)

Mekanisme di balik layar: linter mem-parsing berkas menjadi token dan membangun pohon sintaks, lalu mencocokkan pohon tersebut dengan katalog pola. Karena analisis terjadi pada representasi statis (bukan hasil eksekusi), linter bisa menandai variabel tak terpakai tanpa perlu data uji — dan sebaliknya tidak bisa membuktikan logika benar.

Editor, Code Analyzer App, dan CI #

Tiga pintu masuk analisis yang sama di dunia nyata:

  • Editor MATLAB: linter menyala terus — garis bawah oranye pada kode berisiko; hover menampilkan pesannya. Perbaikan cepat (quick fix) kadang tersedia langsung dari Editor.
  • Code Analyzer App: memindai seluruh folder/proyek sekali jalan dan menyaring temuan per kategori/keparahan — cocok untuk audit besar sebelum rilis.
  • CI / pipeline: checkcode dipanggil batch; karena fungsi ini tidak mengatur exit code sendiri, pembungkus khasnya menghitung temuan lalu error() bila ada yang melebihi ambang (misalnya: nol temuan tinggi). Laporan Cobertura/HTML dari chapter sebelumnya biasa dipasangkan dengan hasil analisis ini.

Padanan Manual: Mini-Linter dengan regexp #

Tanpa checkcode, kita menulis linter kecil yang membaca teks berkas sumber dan menerapkan tiga aturan: variabel diisi tetapi tidak pernah dipakai, nama menimpa fungsi bawaan, dan array yang tumbuh di dalam loop. Berkas contoh.m di bawah halaman ini menerapkan pola itu pada berkas kode_jelek.m buatan sendiri. Potongan aturan pertama dan kedua dari fungsi linterManual():

matlab
% hitung kemunculan nama di seluruh berkas
pola = ['\<' nama '\>'];
jumlah = numel(regexp(teks, pola));

if ismember(nama, namaBawaan)
    temuan(end+1) = struct('baris', b, ...
        'pesan', sprintf(['''%s'' menimpa nama fungsi ' ...
        'bawaan MATLAB'], nama)); %#ok<AGROW>
end
if jumlah == 1
    temuan(end+1) = struct('baris', b, ...
        'pesan', sprintf(['variabel ''%s'' diisi tetapi ' ...
        'tidak pernah dipakai'], nama));
end

Sedangkan deteksi pertumbuhan array memakai backreference \1:

matlab
cocok = regexp(baris{b}, ...
    '^\s*(\w+)\s*=\s*\[\s*\1[\s,]', 'tokens', 'once');
if ~isempty(cocok)
    temuan(end+1) = struct('baris', b, ...
        'pesan', sprintf(['''%s'' tumbuh tiap iterasi, ' ...
        'pertimbangkan zeros() untuk prealokasi'], cocok{1}));
end

Output yang Dihasilkan (dari contoh.m lengkap):

text
== Probe checkcode ==
exist('checkcode') = 0
checkcode tidak tersedia di engine ini (GNU Octave);
menggunakan linter manual berbasis regexp.
== Linter manual: kode_jelek.m ==
L  3 (C 5): variabel 'pajak' diisi tetapi tidak pernah dipakai
L  4 (C 5): 'size' menimpa nama fungsi bawaan MATLAB
L  8 (C 5): 'hasil' tumbuh tiap iterasi, pertimbangkan zeros() untuk prealokasi
Total temuan: 3 (padanan pesan NASGU/shadow/AGROW)
Berkas demo dihapus: sisa = 0

Mari kita bedah baris-baris kode di atas:

  1. Baris 1-3 (pola = ... numel(regexp(teks, pola))): pola \<nama\> dengan word boundary menghitung semua kemunculan identifier di seluruh berkas; bila jumlahnya tepat satu, satu-satunya kemunculan adalah assignment-nya sendiri — variabel itu tidak pernah dipakai.
  2. Baris 5-8 (if ismember(nama, namaBawaan)): aturan shadowing — identifier yang menerima assignment diperiksa terhadap daftar nama fungsi bawaan (sum, size, dan kawan-kawannya).
  3. Baris 10-14 (if jumlah == 1): aturan padanan NASGU; heuristik hitungan kemunculan sengaja sederhana — linter sungguhan melacak aliran data, sedangkan hitungan cukup untuk kasus umum dan mudah dijelaskan.
  4. Blok kedua (regexp ... 'tokens', 'once')): pola ^(\w+) = [ \1 memakai backreference \1 — nama di kiri tanda sama dengan harus muncul lagi tepat setelah kurung siku pembuka, tanda array membungkus dirinya sendiri; bila baris itu berada di dalam blok for, aturan AGROW terpicu.
  5. Keluaran L 3 (C 5):: format L <baris> (C <kolom>) meniru format checkcode agar kebiasaan membaca laporan tetap terpakai saat pindah ke MATLAB. Baris pragma %#ok<AGROW> pada blok pertama juga contoh hidup: kode linter kita sendiri menumbuhkan array struct di loop, lalu dibungkam secara eksplisit.

Ringkasan #

checkcode (penerus nama lama mlint; versi interaktif R2022b+: codeIssues) memindai berkas .m dari Command Window, Editor, atau CI dan melaporkan temuan berformat L baris (C kolom): pesan dengan ID seperti NASGU (variabel tak terpakai), shadowing fungsi bawaan, dan AGROW (array tumbuh dalam loop). Pragma %#ok membungkam pengecualian yang disengaja. Linter manual berbasis regexp di contoh.m menerapkan tiga aturan inti yang sama dan berjalan identik di MATLAB maupun Octave.