mirror of
https://github.com/github/codeql.git
synced 2025-12-20 18:56:32 +01:00
Merge pull request #11177 from github/redsun82/swift-decls
Swift: extract `PoundDiagnosticDecl` and `MissingMemberDecl`
This commit is contained in:
23
swift/extractor/infra/SwiftDiagnosticKind.h
Normal file
23
swift/extractor/infra/SwiftDiagnosticKind.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <swift/AST/DiagnosticConsumer.h>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
inline int translateDiagnosticsKind(swift::DiagnosticKind kind) {
|
||||
using Kind = swift::DiagnosticKind;
|
||||
switch (kind) {
|
||||
case Kind::Error:
|
||||
return 1;
|
||||
case Kind::Warning:
|
||||
return 2;
|
||||
case Kind::Note:
|
||||
return 3;
|
||||
case Kind::Remark:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "swift/extractor/invocation/SwiftDiagnosticsConsumer.h"
|
||||
#include "swift/extractor/trap/generated/TrapEntries.h"
|
||||
#include "swift/extractor/trap/TrapDomain.h"
|
||||
#include "swift/extractor/infra/SwiftDiagnosticKind.h"
|
||||
|
||||
#include <swift/AST/DiagnosticEngine.h>
|
||||
#include <swift/Basic/SourceManager.h>
|
||||
@@ -10,26 +11,12 @@
|
||||
|
||||
using namespace codeql;
|
||||
|
||||
static int diagnosticsKind(const swift::DiagnosticInfo& diagInfo) {
|
||||
switch (diagInfo.Kind) {
|
||||
case swift::DiagnosticKind::Error:
|
||||
return 1;
|
||||
case swift::DiagnosticKind::Warning:
|
||||
return 2;
|
||||
case swift::DiagnosticKind::Note:
|
||||
return 3;
|
||||
case swift::DiagnosticKind::Remark:
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SwiftDiagnosticsConsumer::handleDiagnostic(swift::SourceManager& sourceManager,
|
||||
const swift::DiagnosticInfo& diagInfo) {
|
||||
auto message = getDiagMessage(sourceManager, diagInfo);
|
||||
DiagnosticsTrap diag{};
|
||||
diag.id = trap.createLabel<DiagnosticsTag>();
|
||||
diag.kind = diagnosticsKind(diagInfo);
|
||||
diag.kind = translateDiagnosticsKind(diagInfo.Kind);
|
||||
diag.text = message;
|
||||
trap.emit(diag);
|
||||
locationExtractor.attachLocation(sourceManager, diagInfo.Loc, diagInfo.Loc, diag.id);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <swift/AST/GenericParamList.h>
|
||||
#include <swift/AST/ParameterList.h>
|
||||
#include "swift/extractor/infra/SwiftDiagnosticKind.h"
|
||||
|
||||
namespace codeql {
|
||||
namespace {
|
||||
@@ -401,4 +402,18 @@ std::optional<codeql::OpaqueTypeDecl> DeclTranslator::translateOpaqueTypeDecl(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
codeql::PoundDiagnosticDecl DeclTranslator::translatePoundDiagnosticDecl(
|
||||
const swift::PoundDiagnosticDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
entry.kind = translateDiagnosticsKind(decl.getKind());
|
||||
entry.message = dispatcher.fetchLabel(decl.getMessage());
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::MissingMemberDecl DeclTranslator::translateMissingMemberDecl(
|
||||
const swift::MissingMemberDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
entry.name = decl.getName().getBaseName().userFacingName().str();
|
||||
return entry;
|
||||
}
|
||||
} // namespace codeql
|
||||
|
||||
@@ -46,6 +46,8 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
|
||||
std::optional<codeql::ModuleDecl> translateModuleDecl(const swift::ModuleDecl& decl);
|
||||
codeql::IfConfigDecl translateIfConfigDecl(const swift::IfConfigDecl& decl);
|
||||
std::optional<codeql::OpaqueTypeDecl> translateOpaqueTypeDecl(const swift::OpaqueTypeDecl& decl);
|
||||
codeql::PoundDiagnosticDecl translatePoundDiagnosticDecl(const swift::PoundDiagnosticDecl& decl);
|
||||
codeql::MissingMemberDecl translateMissingMemberDecl(const swift::MissingMemberDecl& decl);
|
||||
|
||||
private:
|
||||
std::string mangledName(const swift::ValueDecl& decl);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.decl.MissingMemberDecl
|
||||
|
||||
class MissingMemberDecl extends Generated::MissingMemberDecl { }
|
||||
class MissingMemberDecl extends Generated::MissingMemberDecl {
|
||||
override string toString() { result = this.getName() + " (missing)" }
|
||||
}
|
||||
|
||||
@@ -2,6 +2,12 @@ private import codeql.swift.generated.decl.PoundDiagnosticDecl
|
||||
|
||||
class PoundDiagnosticDecl extends Generated::PoundDiagnosticDecl {
|
||||
override string toString() {
|
||||
result = "#..." // TODO: Once we extract whether this is an error or a warning we can improve this.
|
||||
this.isError() and result = "#error(...)"
|
||||
or
|
||||
this.isWarning() and result = "#warning(...)"
|
||||
}
|
||||
|
||||
predicate isError() { this.getKind() = 1 }
|
||||
|
||||
predicate isWarning() { this.getKind() = 2 }
|
||||
}
|
||||
|
||||
@@ -373,14 +373,17 @@ private module Impl {
|
||||
private Element getImmediateChildOfPoundDiagnosticDecl(
|
||||
PoundDiagnosticDecl e, int index, string partialPredicateCall
|
||||
) {
|
||||
exists(int b, int bDecl, int n |
|
||||
exists(int b, int bDecl, int n, int nMessage |
|
||||
b = 0 and
|
||||
bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and
|
||||
n = bDecl and
|
||||
nMessage = n + 1 and
|
||||
(
|
||||
none()
|
||||
or
|
||||
result = getImmediateChildOfDecl(e, index - b, partialPredicateCall)
|
||||
or
|
||||
index = n and result = e.getImmediateMessage() and partialPredicateCall = "Message()"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -115,6 +115,8 @@ module Raw {
|
||||
|
||||
class MissingMemberDecl extends @missing_member_decl, Decl {
|
||||
override string toString() { result = "MissingMemberDecl" }
|
||||
|
||||
string getName() { missing_member_decls(this, result) }
|
||||
}
|
||||
|
||||
class OperatorDecl extends @operator_decl, Decl {
|
||||
@@ -131,6 +133,10 @@ module Raw {
|
||||
|
||||
class PoundDiagnosticDecl extends @pound_diagnostic_decl, Decl {
|
||||
override string toString() { result = "PoundDiagnosticDecl" }
|
||||
|
||||
int getKind() { pound_diagnostic_decls(this, result, _) }
|
||||
|
||||
StringLiteralExpr getMessage() { pound_diagnostic_decls(this, _, result) }
|
||||
}
|
||||
|
||||
class PrecedenceGroupDecl extends @precedence_group_decl, Decl {
|
||||
|
||||
@@ -4,7 +4,17 @@ private import codeql.swift.generated.Raw
|
||||
import codeql.swift.elements.decl.Decl
|
||||
|
||||
module Generated {
|
||||
/**
|
||||
* A placeholder for missing declarations that can arise on object deserialization.
|
||||
*/
|
||||
class MissingMemberDecl extends Synth::TMissingMemberDecl, Decl {
|
||||
override string getAPrimaryQlClass() { result = "MissingMemberDecl" }
|
||||
|
||||
/**
|
||||
* Gets the name of this missing member declaration.
|
||||
*/
|
||||
string getName() {
|
||||
result = Synth::convertMissingMemberDeclToRaw(this).(Raw::MissingMemberDecl).getName()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,38 @@
|
||||
private import codeql.swift.generated.Synth
|
||||
private import codeql.swift.generated.Raw
|
||||
import codeql.swift.elements.decl.Decl
|
||||
import codeql.swift.elements.expr.StringLiteralExpr
|
||||
|
||||
module Generated {
|
||||
/**
|
||||
* A diagnostic directive, which is either `#error` or `#warning`.
|
||||
*/
|
||||
class PoundDiagnosticDecl extends Synth::TPoundDiagnosticDecl, Decl {
|
||||
override string getAPrimaryQlClass() { result = "PoundDiagnosticDecl" }
|
||||
|
||||
/**
|
||||
* Gets the This is 1 for `#error` and 2 for `#warning`.
|
||||
*/
|
||||
int getKind() {
|
||||
result = Synth::convertPoundDiagnosticDeclToRaw(this).(Raw::PoundDiagnosticDecl).getKind()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message of this pound diagnostic declaration.
|
||||
*
|
||||
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
|
||||
* behavior of both the `Immediate` and non-`Immediate` versions.
|
||||
*/
|
||||
StringLiteralExpr getImmediateMessage() {
|
||||
result =
|
||||
Synth::convertStringLiteralExprFromRaw(Synth::convertPoundDiagnosticDeclToRaw(this)
|
||||
.(Raw::PoundDiagnosticDecl)
|
||||
.getMessage())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message of this pound diagnostic declaration.
|
||||
*/
|
||||
final StringLiteralExpr getMessage() { result = getImmediateMessage().resolve() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +254,8 @@ import_decl_declarations( //dir=decl
|
||||
);
|
||||
|
||||
missing_member_decls( //dir=decl
|
||||
unique int id: @missing_member_decl
|
||||
unique int id: @missing_member_decl,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
@operator_decl =
|
||||
@@ -288,7 +289,9 @@ pattern_binding_decl_patterns( //dir=decl
|
||||
);
|
||||
|
||||
pound_diagnostic_decls( //dir=decl
|
||||
unique int id: @pound_diagnostic_decl
|
||||
unique int id: @pound_diagnostic_decl,
|
||||
int kind: int ref,
|
||||
int message: @string_literal_expr_or_none ref
|
||||
);
|
||||
|
||||
precedence_group_decls( //dir=decl
|
||||
@@ -2450,6 +2453,11 @@ variadic_sequence_types( //dir=type
|
||||
| @unspecified_element
|
||||
;
|
||||
|
||||
@string_literal_expr_or_none =
|
||||
@string_literal_expr
|
||||
| @unspecified_element
|
||||
;
|
||||
|
||||
@tap_expr_or_none =
|
||||
@tap_expr
|
||||
| @unspecified_element
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// generated by codegen/codegen.py
|
||||
|
||||
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
|
||||
will appear and this file will be deleted
|
||||
@@ -1,4 +0,0 @@
|
||||
// generated by codegen/codegen.py
|
||||
|
||||
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
|
||||
will appear and this file will be deleted
|
||||
@@ -0,0 +1,2 @@
|
||||
| diagnostics.swift:2:1:2:25 | #warning(...) | getModule: | file://:0:0:0:0 | diagnostics | getKind: | 2 | getMessage: | diagnostics.swift:2:10:2:10 | I'm a warning |
|
||||
| diagnostics.swift:3:1:3:26 | #error(...) | getModule: | file://:0:0:0:0 | diagnostics | getKind: | 1 | getMessage: | diagnostics.swift:3:8:3:8 | And I'm an error |
|
||||
@@ -0,0 +1,12 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from PoundDiagnosticDecl x, ModuleDecl getModule, int getKind, StringLiteralExpr getMessage
|
||||
where
|
||||
toBeTested(x) and
|
||||
not x.isUnknown() and
|
||||
getModule = x.getModule() and
|
||||
getKind = x.getKind() and
|
||||
getMessage = x.getMessage()
|
||||
select x, "getModule:", getModule, "getKind:", getKind, "getMessage:", getMessage
|
||||
@@ -0,0 +1,3 @@
|
||||
//codeql-extractor-expected-status: 1
|
||||
#warning("I'm a warning")
|
||||
#error("And I'm an error")
|
||||
@@ -112,8 +112,10 @@ class ImportDecl(Decl):
|
||||
imported_module: optional["ModuleDecl"]
|
||||
declarations: list["ValueDecl"]
|
||||
|
||||
@qltest.skip
|
||||
class MissingMemberDecl(Decl):
|
||||
pass
|
||||
"""A placeholder for missing declarations that can arise on object deserialization."""
|
||||
name: string
|
||||
|
||||
class OperatorDecl(Decl):
|
||||
name: string
|
||||
@@ -123,7 +125,9 @@ class PatternBindingDecl(Decl):
|
||||
patterns: list[Pattern] | child
|
||||
|
||||
class PoundDiagnosticDecl(Decl):
|
||||
pass
|
||||
""" A diagnostic directive, which is either `#error` or `#warning`."""
|
||||
kind: int | doc("""This is 1 for `#error` and 2 for `#warning`""")
|
||||
message: "StringLiteralExpr" | child
|
||||
|
||||
class PrecedenceGroupDecl(Decl):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user