Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,9 @@ coverage --test_env=LLVM_PROFILE_CONTINUOUS_MODE=1
coverage --cxxopt -mllvm
coverage --cxxopt -runtime-counter-relocation

# Clippy linting (enabled by default)
build --aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect
build --output_groups=+clippy_checks
build --@rules_rust//rust/settings:clippy.toml=@score_rust_policies//clippy/strict:clippy.toml

import quality/sanitizer/sanitizer.bazelrc
28 changes: 28 additions & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# *******************************************************************************
# Copyright (c) 2025 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
name: Bazel Clippy

on:
pull_request:
types: [opened, reopened, synchronize]
push:
branches:
- main
merge_group:
types: [checks_requested]

jobs:
bazel-clippy:
uses: eclipse-score/cicd-workflows/.github/workflows/static-analysis.yml@main
with:
bazel-target: "build //:clippy"
27 changes: 27 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

load("@aspect_rules_lint//format:defs.bzl", "format_multirun", "format_test")
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
load("@rules_rust//rust:defs.bzl", "rust_clippy")
load("@score_tooling//:defs.bzl", "copyright_checker")

compile_pip_requirements(
Expand Down Expand Up @@ -55,3 +56,29 @@ format_test(
tags = ["manual"],
workspace = "//:LICENSE",
)

rust_clippy(
name = "clippy",
testonly = True,
tags = ["manual"],
visibility = ["//:__subpackages__"],
deps = [
"//score/mw/com/example/com-api-example/com-api-gen:com-api-gen",
"//score/mw/com/example/com-api-example:com-api-example",
"//score/mw/com/example/ipc_bridge:ipc_bridge_rs",
"//score/mw/com/example/ipc_bridge:ipc_bridge_gen_rs",
"//score/mw/com/example/com-api-example:com-api-example-test",
"//score/mw/com/impl/plumbing:sample_ptr_rs",
"//score/mw/com/impl/rust:common",
"//score/mw/com/impl/rust:macros",
"//score/mw/com/impl/rust:mw_com",
"//score/mw/com/impl/rust:proxy_bridge_rs",
"//score/mw/com/impl/rust:skeleton_bridge_rs",
"//score/mw/com/impl/rust/com-api/com-api:com-api",
"//score/mw/com/impl/rust/com-api/com-api-concept:com-api-concept",
"//score/mw/com/impl/rust/com-api/com-api-concept:com-api-concept-test",
"//score/mw/com/impl/rust/com-api/com-api-runtime-lola:com-api-runtime-lola",
"//score/mw/com/impl/rust/com-api/com-api-runtime-mock:com-api-runtime-mock",
"//score/mw/com/impl/rust/test:proxy_bridge_integration_test",
],
)
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ bazel_dep(name = "aspect_rules_lint", version = "1.10.2")
bazel_dep(name = "googletest", version = "1.15.0")
bazel_dep(name = "google_benchmark", version = "1.9.1")
bazel_dep(name = "rules_rust", version = "0.61.0")
bazel_dep(name = "score_rust_policies", version = "0.0.2", dev_dependency = True)
bazel_dep(name = "buildifier_prebuilt", version = "6.3.3")
bazel_dep(name = "score_crates", version = "0.0.4", repo_name = "crate_index")

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ bazel test //...
bazel build //score/mw/com:all
```

## Clippy

- Clippy runs by default via `.bazelrc` when building Rust targets.
- Use `bazel build //:clippy` for an explicit lint-only target, or `bazel build //score/mw/com/...` while developing.
- The Clippy config comes from `@score_rust_policies//clippy/strict:clippy.toml`.

## Project Structure

```
Expand Down
6 changes: 5 additions & 1 deletion score/mw/com/example/com-api-example/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ rust_binary(
rust_test(
name = "com-api-example-test",
crate = ":com-api-example",
tags = ["manual"],
tags = [
"manual",
"no-clippy",
],
visibility = ["//:__subpackages__"],
deps = [
"//score/mw/com/example/com-api-example/com-api-gen",
"//score/mw/com/impl/rust/com-api/com-api",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,14 @@ fn use_consumer<R: Runtime>(runtime: &R) -> VehicleConsumer<R> {
.find(|desc| desc.get_instance_identifier().as_ref() == "/My/Funk/ServiceName")
.unwrap();

let consumer = consumer_builder.build().unwrap();
//
consumer
consumer_builder.build().unwrap()
}

fn use_producer<R: Runtime>(runtime: &R) -> VehicleOfferedProducer<R> {
let producer_builder = runtime.producer_builder::<VehicleInterface, VehicleProducer<R>>(
InstanceSpecifier::new("/My/Funk/ServiceName").unwrap(),
);
let producer = producer_builder.build().unwrap();
let offered_producer = producer.offer().unwrap();
offered_producer
producer_builder.build().unwrap().offer().unwrap()
}

fn run_with_runtime<R: Runtime>(name: &str, runtime: &R) {
Expand Down
3 changes: 2 additions & 1 deletion score/mw/com/example/ipc_bridge/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ rust_library(
name = "ipc_bridge_gen_rs",
srcs = ["ipc_bridge_gen.rs"],
visibility = [
"//score/mw/com:__subpackages__",
"//:__subpackages__",
],
deps = [
":ipc_bridge_gen_cpp",
Expand All @@ -82,6 +82,7 @@ rust_binary(
data = ["etc/mw_com_config.json"],
features = ["link_std_cpp_lib"],
rustc_flags = ["-Clink-arg=-lstdc++"],
visibility = ["//:__subpackages__"],
deps = [
":ipc_bridge_gen_rs",
"//score/mw/com/impl/rust:mw_com",
Expand Down
20 changes: 10 additions & 10 deletions score/mw/com/example/ipc_bridge/ipc_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ fn run<F: std::future::Future<Output = ()> + Send>(future: F) {
futures::executor::block_on(future);
}

fn run_recv_mode(instance_specifier: mw_com::InstanceSpecifier) {
let handles = loop {
let handles = mw_com::proxy::find_service(instance_specifier.clone())
.expect("Instance specifier resolution failed");
if handles.len() > 0 {
break handles;
} else {
println!("No service found, retrying in 1 second");
sleep(SERVICE_DISCOVERY_SLEEP_DURATION);
}
fn run_recv_mode(instance_specifier: mw_com::InstanceSpecifier) {
let handles = loop {
let handles = mw_com::proxy::find_service(instance_specifier.clone())
.expect("Instance specifier resolution failed");
if !handles.is_empty() {
break handles;
} else {
println!("No service found, retrying in 1 second");
sleep(SERVICE_DISCOVERY_SLEEP_DURATION);
}
};

let ipc_bridge_gen_rs::IpcBridge::Proxy {
Expand Down
25 changes: 8 additions & 17 deletions score/mw/com/example/ipc_bridge/ipc_bridge_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,27 @@
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
///! This is the "generated" part for the ipc_bridge proxy. Its main purpose is to provide the imports
///! of the type- and name-dependent part of the FFI and create the respective user-facing objects.
use std::default::Default;
********************************************************************************/
#![allow(clippy::not_unsafe_ptr_arg_deref)]
//! This is the "generated" part for the ipc_bridge proxy. Its main purpose is to provide the imports
//! of the type- and name-dependent part of the FFI and create the respective user-facing objects.
use std::ffi::c_char;

pub const MAX_SUCCESSORS: libc::size_t = 16;
pub const MAX_LANES: libc::size_t = 16;

#[repr(u32)]
#[derive(Default)]
pub enum StdTimestampSyncState {
#[allow(non_camel_case_types)]
kStdTimestampSyncState_InSync = 0,
#[allow(non_camel_case_types)]
kStdTimestampSyncState_NotInSync = 1,
#[allow(non_camel_case_types)]
#[default]
kStdTimestampSyncState_Invalid = 255,
}

impl Default for StdTimestampSyncState {
fn default() -> Self {
StdTimestampSyncState::kStdTimestampSyncState_Invalid
}
}

#[repr(C)]
#[derive(Default)]
pub struct StdTimestamp {
Expand All @@ -43,7 +39,7 @@ pub struct StdTimestamp {
}

#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum EventDataQualifier {
/// @brief Event data available, normal operation.
///
Expand All @@ -61,6 +57,7 @@ pub enum EventDataQualifier {
/// on the reason for non-availability.
///
/// The remaining information in the scope of the event (except extendedQualifier) must not be evaluated.
#[default]
EventDataNotAvailable = 2,
/// @brief There is no event data available, due to the event data being invalid (e.g. CRC error) or due to a
/// timeout.
Expand All @@ -69,12 +66,6 @@ pub enum EventDataQualifier {
EventDataInvalid = 255,
}

impl Default for EventDataQualifier {
fn default() -> Self {
EventDataQualifier::EventDataNotAvailable
}
}

#[repr(C)]
#[derive(Default)]
pub struct MapApiLaneBoundaryData {
Expand Down
2 changes: 1 addition & 1 deletion score/mw/com/impl/plumbing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ rust_library(
name = "sample_ptr_rs",
srcs = ["sample_ptr.rs"],
visibility = [
"//score/mw/com:__subpackages__",
"//:__subpackages__",
],
deps = ["@crate_index//:libc"],
)
6 changes: 4 additions & 2 deletions score/mw/com/impl/rust/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ load("//score/mw:common_features.bzl", "COMPILER_WARNING_FEATURES")
rust_library(
name = "common",
srcs = ["common.rs"],
visibility = ["//:__subpackages__"],
)

cc_library(
Expand Down Expand Up @@ -66,7 +67,7 @@ rust_library(
name = "proxy_bridge_rs",
srcs = ["proxy_bridge.rs"],
visibility = [
"//score/mw/com:__subpackages__",
"//:__subpackages__",
],
deps = [
":proxy_bridge_cpp",
Expand All @@ -80,7 +81,7 @@ rust_library(
name = "skeleton_bridge_rs",
srcs = ["skeleton_bridge.rs"],
visibility = [
"//score/mw/com:__subpackages__",
"//:__subpackages__",
],
deps = [
":common",
Expand All @@ -93,6 +94,7 @@ rust_library(
proc_macro_deps = [
"@crate_index//:paste",
],
visibility = ["//:__subpackages__"],
deps = [
":common",
":proxy_bridge_rs",
Expand Down
6 changes: 5 additions & 1 deletion score/mw/com/impl/rust/com-api/com-api-concept/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ rust_library(
rust_test(
name = "com-api-concept-test",
crate = ":com-api-concept",
tags = ["manual"],
tags = [
"manual",
"no-clippy",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no clippy ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rust_test

],
visibility = ["//:__subpackages__"],
deps = [":com-api-concept"],
)
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,13 @@ impl InstanceSpecifier {
let service_name = service_name.strip_prefix('/').unwrap();

// Check each character
let is_legal_char = |c| {
(c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
};
let is_legal_char = |c: char| c.is_ascii_alphanumeric() || c == '_';

//validation of each path segment
!service_name.is_empty()
&& service_name.split('/').all(|parts| {
// No empty segments (reject trailing "/" and "//" in the middle)
!parts.is_empty() && parts.chars().all(|c| is_legal_char(c))
!parts.is_empty() && parts.chars().all(is_legal_char)
})
}

Expand Down Expand Up @@ -249,9 +247,9 @@ pub enum FindServiceSpecifier {
}

/// Convert an InstanceSpecifier into a FindServiceSpecifier
impl Into<FindServiceSpecifier> for InstanceSpecifier {
fn into(self) -> FindServiceSpecifier {
FindServiceSpecifier::Specific(self)
impl From<InstanceSpecifier> for FindServiceSpecifier {
fn from(val: InstanceSpecifier) -> Self {
FindServiceSpecifier::Specific(val)
}
}

Expand All @@ -269,7 +267,6 @@ impl Into<FindServiceSpecifier> for InstanceSpecifier {
///
/// Since it is yet to be proven whether this trait can be implemented safely (assumption is: no) it
/// is unsafe for now. The expectation is that very few users ever need to implement this manually.

/// A `Sample` provides a reference to a memory buffer of an event with immutable value.
///
/// By implementing the `Deref` trait implementations of the trait support the `.` operator for dereferencing.
Expand Down Expand Up @@ -437,7 +434,7 @@ where
/// # Returns
///
/// A 'Result' containing the allocated sample buffer on success and an 'Error' on failure.
fn allocate<'a>(&'a self) -> Result<Self::SampleMaybeUninit<'a>>;
fn allocate(&self) -> Result<Self::SampleMaybeUninit<'_>>;

/// Allocate, initialize, and send an event sample in one step.
///
Expand Down
7 changes: 7 additions & 0 deletions score/mw/com/impl/rust/com-api/com-api-concept/reloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

/// Marker trait for relocatable types used across FFI boundaries.
///
/// # Safety
///
/// Implementors must ensure the type has no self-references or other invariants that would be
/// violated by moving the value in memory. Only types that remain valid under relocation should
/// implement this trait.
pub unsafe trait Reloc {}

unsafe impl Reloc for () {}
Expand Down
Loading