diff --git a/ruby/ql/consistency-queries/AstConsistency.ql b/ruby/ql/consistency-queries/AstConsistency.ql index 2a9fea8fea9..d7792a8ae4d 100644 --- a/ruby/ql/consistency-queries/AstConsistency.ql +++ b/ruby/ql/consistency-queries/AstConsistency.ql @@ -31,3 +31,5 @@ query predicate multipleToString(AstNode n, string s) { } query predicate extractionError(ExtractionError error) { any() } + +query predicate extractionWarning(ExtractionWarning error) { any() } diff --git a/ruby/ql/lib/change-notes/2024-10-03-extraction-warnings.md b/ruby/ql/lib/change-notes/2024-10-03-extraction-warnings.md new file mode 100644 index 00000000000..5d6128354c3 --- /dev/null +++ b/ruby/ql/lib/change-notes/2024-10-03-extraction-warnings.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `ExtractionError` class has been split into `ExtractionError` and `ExtractionWarning`, reporting extraction errors and warnings respectively. diff --git a/ruby/ql/lib/codeql/ruby/AST.qll b/ruby/ql/lib/codeql/ruby/AST.qll index e8dc28692c0..bd42696a8db 100644 --- a/ruby/ql/lib/codeql/ruby/AST.qll +++ b/ruby/ql/lib/codeql/ruby/AST.qll @@ -18,6 +18,7 @@ private import ast.internal.Scope private import ast.internal.Synthesis private import ast.internal.TreeSitter private import Customizations +private import Diagnostics cached private module Cached { @@ -166,3 +167,20 @@ class RubyFile extends File { /** Gets the number of lines of comments in this file. */ int getNumberOfLinesOfComments() { result = count(int line | this.line(line, true)) } } + +/** + * A successfully extracted file, that is, a file that was extracted and + * contains no extraction errors or warnings. + */ +class SuccessfullyExtractedFile extends File { + SuccessfullyExtractedFile() { + not exists(Diagnostic d | + d.getLocation().getFile() = this and + ( + d instanceof ExtractionError + or + d instanceof ExtractionWarning + ) + ) + } +} diff --git a/ruby/ql/lib/codeql/ruby/Diagnostics.qll b/ruby/ql/lib/codeql/ruby/Diagnostics.qll index 5902bb59414..58de14b8fcf 100644 --- a/ruby/ql/lib/codeql/ruby/Diagnostics.qll +++ b/ruby/ql/lib/codeql/ruby/Diagnostics.qll @@ -48,7 +48,8 @@ class Diagnostic extends @diagnostic { string toString() { result = this.getMessage() } } -/** A diagnostic relating to a particular error in extracting a file. */ -class ExtractionError extends Diagnostic { - ExtractionError() { this.getTag() = "parse_error" } -} +/** A diagnostic that is error severity. */ +class ExtractionError extends Diagnostic, @diagnostic_error { } + +/** A diagnostic that is warning severity. */ +class ExtractionWarning extends Diagnostic, @diagnostic_warning { } diff --git a/ruby/ql/src/change-notes/2024-10-03-extraction-warnings.md b/ruby/ql/src/change-notes/2024-10-03-extraction-warnings.md new file mode 100644 index 00000000000..ac97cd1e7ba --- /dev/null +++ b/ruby/ql/src/change-notes/2024-10-03-extraction-warnings.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `rb/diagnostics/extraction-errors` diagnostic query has been split into `rb/diagnostics/extraction-errors` and `rb/diagnostics/extraction-warnings`, counting extraction errors and warnings respectively. diff --git a/ruby/ql/src/queries/diagnostics/ExtractionWarnings.ql b/ruby/ql/src/queries/diagnostics/ExtractionWarnings.ql new file mode 100644 index 00000000000..74f00739056 --- /dev/null +++ b/ruby/ql/src/queries/diagnostics/ExtractionWarnings.ql @@ -0,0 +1,19 @@ +/** + * @name Extraction warnings + * @description List all extraction warnings for files in the source code directory. + * @kind diagnostic + * @id rb/diagnostics/extraction-warnings + */ + +import codeql.ruby.AST +import codeql.ruby.Diagnostics + +/** Gets the SARIF severity to associate with a warning. */ +int getSeverity() { result = 1 } + +from ExtractionWarning warning, File f +where + f = warning.getLocation().getFile() and + exists(f.getRelativePath()) +select warning, "Extraction warning in " + f + " with message " + warning.getMessage(), + getSeverity() diff --git a/ruby/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql b/ruby/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql index 8623ed911d5..1cbc28b6cc6 100644 --- a/ruby/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql +++ b/ruby/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql @@ -2,14 +2,15 @@ * @id rb/summary/number-of-files-extracted-with-errors * @name Total number of Ruby files that were extracted with errors * @description The total number of Ruby code files that we extracted, but where - * at least one extraction error occurred in the process. + * at least one extraction error (or warning) occurred in the process. * @kind metric * @tags summary */ import codeql.ruby.AST -import codeql.ruby.Diagnostics +import codeql.files.FileSystem select count(File f | - exists(ExtractionError e | e.getLocation().getFile() = f) and exists(f.getRelativePath()) + exists(f.getRelativePath()) and + not f instanceof SuccessfullyExtractedFile ) diff --git a/ruby/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql b/ruby/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql index 236374ff226..afd667cf58c 100644 --- a/ruby/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql +++ b/ruby/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql @@ -2,14 +2,12 @@ * @id rb/summary/number-of-successfully-extracted-files * @name Total number of Ruby files that were extracted without error * @description The total number of Ruby code files that we extracted without - * encountering any extraction errors + * encountering any extraction errors (or warnings). * @kind metric * @tags summary */ import codeql.ruby.AST -import codeql.ruby.Diagnostics +import codeql.files.FileSystem -select count(File f | - not exists(ExtractionError e | e.getLocation().getFile() = f) and exists(f.getRelativePath()) - ) +select count(SuccessfullyExtractedFile f | exists(f.getRelativePath())) diff --git a/ruby/ql/test/query-tests/diagnostics/CONSISTENCY/AstConsistency.expected b/ruby/ql/test/query-tests/diagnostics/CONSISTENCY/AstConsistency.expected index 5dc14116b91..93df75151a7 100644 --- a/ruby/ql/test/query-tests/diagnostics/CONSISTENCY/AstConsistency.expected +++ b/ruby/ql/test/query-tests/diagnostics/CONSISTENCY/AstConsistency.expected @@ -1,2 +1,2 @@ -extractionError +extractionWarning | src/not_ruby.rb:5:25:5:26 | A parse error occurred. Check the syntax of the file. If the file is invalid, correct the error or exclude the file from analysis. | diff --git a/ruby/ql/test/query-tests/diagnostics/ExtractionErrors.expected b/ruby/ql/test/query-tests/diagnostics/ExtractionErrors.expected index dc37ca3642b..e69de29bb2d 100644 --- a/ruby/ql/test/query-tests/diagnostics/ExtractionErrors.expected +++ b/ruby/ql/test/query-tests/diagnostics/ExtractionErrors.expected @@ -1 +0,0 @@ -| src/not_ruby.rb:5:25:5:26 | A parse error occurred. Check the syntax of the file. If the file is invalid, correct the error or exclude the file from analysis. | Extraction failed in src/not_ruby.rb with error A parse error occurred. Check the syntax of the file. If the file is invalid, correct the error or exclude the file from analysis. | 2 | diff --git a/ruby/ql/test/query-tests/diagnostics/ExtractionWarnings.expected b/ruby/ql/test/query-tests/diagnostics/ExtractionWarnings.expected new file mode 100644 index 00000000000..c47ec9c5d36 --- /dev/null +++ b/ruby/ql/test/query-tests/diagnostics/ExtractionWarnings.expected @@ -0,0 +1 @@ +| src/not_ruby.rb:5:25:5:26 | A parse error occurred. Check the syntax of the file. If the file is invalid, correct the error or exclude the file from analysis. | Extraction warning in src/not_ruby.rb with message A parse error occurred. Check the syntax of the file. If the file is invalid, correct the error or exclude the file from analysis. | 1 | diff --git a/ruby/ql/test/query-tests/diagnostics/ExtractionWarnings.qlref b/ruby/ql/test/query-tests/diagnostics/ExtractionWarnings.qlref new file mode 100644 index 00000000000..ff6e566d20a --- /dev/null +++ b/ruby/ql/test/query-tests/diagnostics/ExtractionWarnings.qlref @@ -0,0 +1 @@ +queries/diagnostics/ExtractionWarnings.ql diff --git a/rust/ql/consistency-queries/ExtractionConsistency.ql b/rust/ql/consistency-queries/ExtractionConsistency.ql index b839f2ad783..20148f0cea2 100644 --- a/rust/ql/consistency-queries/ExtractionConsistency.ql +++ b/rust/ql/consistency-queries/ExtractionConsistency.ql @@ -1,3 +1,5 @@ import codeql.rust.Diagnostics query predicate extractionError(ExtractionError ee) { any() } + +query predicate extractionWarning(ExtractionWarning ew) { any() } diff --git a/rust/ql/lib/codeql/files/FileSystem.qll b/rust/ql/lib/codeql/files/FileSystem.qll index 95ca925a884..7136dcc3b5a 100644 --- a/rust/ql/lib/codeql/files/FileSystem.qll +++ b/rust/ql/lib/codeql/files/FileSystem.qll @@ -5,6 +5,7 @@ private import codeql.util.FileSystem private import codeql.rust.elements.SourceFile private import codeql.rust.elements.AstNode private import codeql.rust.elements.Comment +private import codeql.rust.Diagnostics private module Input implements InputSig { abstract class ContainerBase extends @container { @@ -56,3 +57,20 @@ class File extends Container, Impl::File { ) } } + +/** + * A successfully extracted file, that is, a file that was extracted and + * contains no extraction errors or warnings. + */ +class SuccessfullyExtractedFile extends File { + SuccessfullyExtractedFile() { + not exists(Diagnostic d | + d.getLocation().getFile() = this and + ( + d instanceof ExtractionError + or + d instanceof ExtractionWarning + ) + ) + } +} diff --git a/rust/ql/lib/codeql/rust/Diagnostics.qll b/rust/ql/lib/codeql/rust/Diagnostics.qll index 5902bb59414..58de14b8fcf 100644 --- a/rust/ql/lib/codeql/rust/Diagnostics.qll +++ b/rust/ql/lib/codeql/rust/Diagnostics.qll @@ -48,7 +48,8 @@ class Diagnostic extends @diagnostic { string toString() { result = this.getMessage() } } -/** A diagnostic relating to a particular error in extracting a file. */ -class ExtractionError extends Diagnostic { - ExtractionError() { this.getTag() = "parse_error" } -} +/** A diagnostic that is error severity. */ +class ExtractionError extends Diagnostic, @diagnostic_error { } + +/** A diagnostic that is warning severity. */ +class ExtractionWarning extends Diagnostic, @diagnostic_warning { } diff --git a/rust/ql/src/queries/diagnostics/ExtractionErrors.ql b/rust/ql/src/queries/diagnostics/ExtractionErrors.ql index a04c4e618c4..68be66f8ca9 100644 --- a/rust/ql/src/queries/diagnostics/ExtractionErrors.ql +++ b/rust/ql/src/queries/diagnostics/ExtractionErrors.ql @@ -8,7 +8,7 @@ import codeql.rust.Diagnostics import codeql.files.FileSystem -/** Gets the SARIF severity to associate an error. */ +/** Gets the SARIF severity to associate with an error. */ int getSeverity() { result = 2 } from ExtractionError error, File f diff --git a/rust/ql/src/queries/diagnostics/ExtractionWarnings.ql b/rust/ql/src/queries/diagnostics/ExtractionWarnings.ql new file mode 100644 index 00000000000..99773cc6d53 --- /dev/null +++ b/rust/ql/src/queries/diagnostics/ExtractionWarnings.ql @@ -0,0 +1,19 @@ +/** + * @name Extraction warnings + * @description List all extraction warnings for files in the source code directory. + * @kind diagnostic + * @id rust/diagnostics/extraction-warnings + */ + +import codeql.rust.Diagnostics +import codeql.files.FileSystem + +/** Gets the SARIF severity to associate with a warning. */ +int getSeverity() { result = 1 } + +from ExtractionWarning warning, File f +where + f = warning.getLocation().getFile() and + exists(f.getRelativePath()) +select warning, "Extraction warning in " + f + " with message " + warning.getMessage(), + getSeverity() diff --git a/rust/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql b/rust/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql index 1af3f0f88ec..23db30f53e9 100644 --- a/rust/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql +++ b/rust/ql/src/queries/summary/NumberOfFilesExtractedWithErrors.ql @@ -2,14 +2,15 @@ * @id rust/summary/number-of-files-extracted-with-errors * @name Total number of Rust files that were extracted with errors * @description The total number of Rust files in the source code directory that - * were extracted, but where at least one extraction error occurred in the process. + * were extracted, but where at least one extraction error (or warning) occurred + * in the process. * @kind metric * @tags summary */ import codeql.files.FileSystem -import codeql.rust.Diagnostics select count(File f | - exists(ExtractionError e | e.getLocation().getFile() = f) and exists(f.getRelativePath()) + exists(f.getRelativePath()) and + not f instanceof SuccessfullyExtractedFile ) diff --git a/rust/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql b/rust/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql index eb86577b4b8..c960599ad18 100644 --- a/rust/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql +++ b/rust/ql/src/queries/summary/NumberOfSuccessfullyExtractedFiles.ql @@ -2,14 +2,11 @@ * @id rust/summary/number-of-successfully-extracted-files * @name Total number of Rust files that were extracted without error * @description The total number of Rust files in the source code directory that - * were extracted without encountering any extraction errors. + * were extracted without encountering any extraction errors (or warnings). * @kind metric * @tags summary */ -import codeql.rust.Diagnostics import codeql.files.FileSystem -select count(File f | - not exists(ExtractionError e | e.getLocation().getFile() = f) and exists(f.getRelativePath()) - ) +select count(SuccessfullyExtractedFile f | exists(f.getRelativePath())) diff --git a/rust/ql/src/queries/summary/SummaryStats.ql b/rust/ql/src/queries/summary/SummaryStats.ql index 447325514ca..a3494ccb769 100644 --- a/rust/ql/src/queries/summary/SummaryStats.ql +++ b/rust/ql/src/queries/summary/SummaryStats.ql @@ -7,16 +7,29 @@ */ import rust +import codeql.rust.Diagnostics import Stats from string key, string value where - key = "Files extracted" and value = count(File f | exists(f.getRelativePath())).toString() - or key = "Elements extracted" and value = count(Element e | not e instanceof Unextracted).toString() or key = "Elements unextracted" and value = count(Unextracted e).toString() or + key = "Extraction errors" and value = count(ExtractionError e).toString() + or + key = "Extraction warnings" and value = count(ExtractionWarning w).toString() + or + key = "Files extracted - total" and value = count(File f | exists(f.getRelativePath())).toString() + or + key = "Files extracted - with errors" and + value = + count(File f | exists(f.getRelativePath()) and not f instanceof SuccessfullyExtractedFile) + .toString() + or + key = "Files extracted - without errors" and + value = count(SuccessfullyExtractedFile f | exists(f.getRelativePath())).toString() + or key = "Lines of code extracted" and value = getLinesOfCode().toString() or key = "Lines of user code extracted" and value = getLinesOfUserCode().toString() diff --git a/rust/ql/test/extractor-tests/utf8/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/extractor-tests/utf8/CONSISTENCY/ExtractionConsistency.expected index 23b423a489a..45026be3af2 100644 --- a/rust/ql/test/extractor-tests/utf8/CONSISTENCY/ExtractionConsistency.expected +++ b/rust/ql/test/extractor-tests/utf8/CONSISTENCY/ExtractionConsistency.expected @@ -1,3 +1,4 @@ +extractionWarning | lib.rs:3:9:3:8 | expected `;` or `{` | | lib.rs:3:9:3:8 | expected an item | | lib.rs:3:21:3:20 | expected BANG | diff --git a/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected index 157aafc8785..0d5ffb09561 100644 --- a/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected +++ b/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected @@ -1,3 +1,4 @@ +extractionWarning | does_not_compile.rs:2:6:2:5 | expected SEMICOLON | | does_not_compile.rs:2:9:2:8 | expected SEMICOLON | | does_not_compile.rs:2:13:2:12 | expected SEMICOLON | diff --git a/rust/ql/test/query-tests/diagnostics/ExtractionErrors.expected b/rust/ql/test/query-tests/diagnostics/ExtractionErrors.expected index b6aaf7b6d37..e69de29bb2d 100644 --- a/rust/ql/test/query-tests/diagnostics/ExtractionErrors.expected +++ b/rust/ql/test/query-tests/diagnostics/ExtractionErrors.expected @@ -1,6 +0,0 @@ -| does_not_compile.rs:2:6:2:5 | expected SEMICOLON | Extraction failed in does_not_compile.rs with error expected SEMICOLON | 2 | -| does_not_compile.rs:2:9:2:8 | expected SEMICOLON | Extraction failed in does_not_compile.rs with error expected SEMICOLON | 2 | -| does_not_compile.rs:2:13:2:12 | expected SEMICOLON | Extraction failed in does_not_compile.rs with error expected SEMICOLON | 2 | -| does_not_compile.rs:2:21:2:20 | expected SEMICOLON | Extraction failed in does_not_compile.rs with error expected SEMICOLON | 2 | -| does_not_compile.rs:2:26:2:25 | expected SEMICOLON | Extraction failed in does_not_compile.rs with error expected SEMICOLON | 2 | -| does_not_compile.rs:2:32:2:31 | expected field name or number | Extraction failed in does_not_compile.rs with error expected field name or number | 2 | diff --git a/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected new file mode 100644 index 00000000000..0a68f2bce0e --- /dev/null +++ b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected @@ -0,0 +1,6 @@ +| does_not_compile.rs:2:6:2:5 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | +| does_not_compile.rs:2:9:2:8 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | +| does_not_compile.rs:2:13:2:12 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | +| does_not_compile.rs:2:21:2:20 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | +| does_not_compile.rs:2:26:2:25 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | +| does_not_compile.rs:2:32:2:31 | expected field name or number | Extraction warning in does_not_compile.rs with message expected field name or number | 1 | diff --git a/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.qlref b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.qlref new file mode 100644 index 00000000000..ff6e566d20a --- /dev/null +++ b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.qlref @@ -0,0 +1 @@ +queries/diagnostics/ExtractionWarnings.ql diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected index d9142bcadfe..16ed88fcaa4 100644 --- a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected +++ b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected @@ -1,5 +1,9 @@ | Elements extracted | 290 | | Elements unextracted | 0 | -| Files extracted | 7 | +| Extraction errors | 0 | +| Extraction warnings | 6 | +| Files extracted - total | 7 | +| Files extracted - with errors | 1 | +| Files extracted - without errors | 6 | | Lines of code extracted | 61 | | Lines of user code extracted | 61 |