Skip to content

Foretify Linter rules

The Foretify Linter identifies problematic use of the OSC2 language. You can use the linter to enforce best practices for code used with Foretellix scenarios and libraries.

Problematic uses of OSC2 are defined as a list of named rules. These rules are defined below.

You can load a configuration file that defines the severity level for each rule. You can also specify in your OSC2 source files if there are lines you want the linter to ignore. See Using the Foretify linter for more information.

LINT_ABSOLUTE_SPEED

The LINT_ABSOLUTE_SPEED rule specifies that it is better to use speed(at: start) followed by keep_speed() or change_speed() instead of an absolute speed(at: all).

OSC2 code: preferred style of no absolute speed
# instead of:
sut.car.drive() with:
    speed(50kph, at: all)

# do this:
sut.car.drive() with:
    speed(50kph, at: start)
    keep_speed()

For more information, see Avoid specifying absolute speed for an entire movement.

LINT_ACTOR_FIELD_NAME

The LINT_ACTOR_FIELD_NAME rule requires the names of actors that play a specific role in a scenario to be in the format <action>_<type>[_number]. For example: cut_in_vehicle or cut_in_vehicle_1.

OSC2 code: preferred style of actor field names
# instead of:
extend top.main:
    car1: vehicle
    car2: vehicle

# do this:
extend top.main:
    cut_in_vehicle_1: vehicle
    cut_in_vehicle_2: vehicle

For more information, see Actor naming.

LINT_ADAS_FUNC_NOT_PREFIX

The LINT_ADAS_FUNC_NOT_PREFIX rule requires that if you use a standard ADAS acronym such as acc or aeb in a name, it must be the prefix.

OSC2 code: preferred use of ADAS function in name
# instead of:

scenario sut.highway_drive_acc:
    road: highway

# prefer:
scenario sut.acc_highway_drive:
    road: highway

For more information, see Scenario naming.

LINT_CROSS_BAD_PREFIX

The LINT_CROSS_BAD_PREFIX rule requires that the name of cross metrics start with the prefix cross_ and include the name of each item connected by _. For example, for a cross between sut_speed and sut_acceleration, the name should be cross_sut_speed_sut_acceleration or cross_sut_acceleration_sut_speed.

OSC2 code: preferred name of cross coverage
# Instead of

extend top.main:
    overtake_vehicle: vehicle
    overtake_vehicle_init_speed: speed
    overtake_vehicle_init_direction: direction

    cover(overtake_vehicle_init_speed, unit:kph)
    cover(overtake_vehicle_init_direction)

    cover(cross_overtake_vehicle_init_speed_direction,
        items: [overtake_vehicle_init_speed, overtake_vehicle_init_direction])


# Prefer

extend top.main:
    overtake_vehicle: vehicle
    overtake_vehicle_init_speed: speed
    overtake_vehicle_init_direction: direction

    cover(overtake_vehicle_init_speed, unit:kph)
    cover(overtake_vehicle_init_direction)


    cover(cross_overtake_vehicle_init_speed_overtake_vehicle_init_direction,
        items: [overtake_vehicle_init_speed, overtake_vehicle_init_direction])

For more information, see Naming convention for cross-coverage items.

LINT_DURATION_IN_CONSTRAINT

The LINT_DURATION_IN_CONSTRAINT rule disallows constraining the duration parameter of a scenario in a keep() constraint or via scenario invocation. Instead, constrain duration using the duration() modifier.

OSC2 code: preferred style of no duration in constraint
# instead of:
extend top.main:

    keep(d1.duration in [3..5]second)

    do d1: sut.car.drive() with: speed([40..50]kph)


# prefer:
extend top.main:

    do d1: sut.car.drive() with:
        speed([40..50]kph)
        duration([3..5]second)

# or prefer:
extend top.main:

    in d1 with: duration([3..5]second)

    do d1: sut.car.drive() with: speed([40..50]kph)

#instead of:
scenario my_drive:

    do sut.car.drive()


extend top.main:

    do md: my_drive(duration: [3..5]s)



#prefer

scenario my_drive:

    do sut.car.drive()

extend top.main:

    do md: my_drive() with:
         duration([3..5]s)

For more information, see Use duration() to constrain a scenario's duration.

LINT_METRICS_BAD_UNIT

The LINT_METRICS_BAD_UNIT rule requires the use of a specific unit for certain types:

  • For speed: kph.
  • For length: meter.
  • For acceleration: mpsps.
  • For time: second.
OSC2 code: preferred use of recommended unit in coverage
# Instead of

extend top.main:
    speed1: speed
    direction1: direction

    cover(my_speed, expression: speed1, unit: mps)
    cover(my_direction, expression: direction1)

# Prefer

extend top.main:
    speed1: speed
    direction1: direction

    cover(my_speed, expression: speed1, unit: kph)
    cover(my_direction, expression: direction1)

Tip

You can configure how units are displayed. See Display unit options for details.

For more information, see Use of physical units.

LINT_MIX_TOLERANCE_AND_BEST_EFFORT

The LINT_MIX_TOLERANCE_AND_BEST_EFFORT rule requires that you either specify a tolerance parameter for a movement modifier or override the movement modifier with the best_effort run mode rather than using both.

OSC2 code: preferred style of tolerance or best_effort
# instead of:
extend top.main:

    in d1 with: override(drive_speed, run_mode: best_effort)

    do d1: sut.car.drive() with:
        drive_speed: speed([30..50]kph, tolerance: [1..3]kph)

# prefer:
extend top.main:

    in d1 with: override(drive_speed, run_mode: best_effort)

    do d1: sut.car.drive() with:
        drive_speed: speed([30..50]kph)

# or prefer
extend top.main:

    do d1: sut.car.drive() with:
        drive_speed: speed([30..50]kph, tolerance: [1..3]kph)

For more information, see Use best_effort or tolerance.

LINT_RELATIONAL_EGO_DRIVE

The LINT_RELATIONAL_EGO_DRIVE rule specifies that when using relative modifiers such as speed() and position() with NPC and sut.car, the reference vehicle should be sut.car rather than the NPC.

OSC2 code: preferred style of relative to Ego
# instead of:
sut.car.drive() with:
    speed(10kph, faster_than: car1)

# do this:
car1.drive() with:
    speed(10kph, slower_than: sut.car)

For more information, see Do not define the SUT's movements relative to other actors.

LINT_SNAKE_CASE

The LINT_SNAKE_CASE rule requires all identifiers to be lowercase names separated by underscores.

OSC2 code: preferred style of snake case
# instead of:
extend top.main:
    cutinVehicle: vehicle

# prefer:
extend top.main:
    cut_in_vehicle: vehicle

For more information, see Snake case formatting.

LINT_STANDARD_NAMING

The LINT_STANDARD_NAMING rule requires that you follow certain naming conventions:

  • Use sut to refer to the System Under Test, not ego or dut. For example, use sut_speed rather than ego_speed.
  • Use vehicle to name actors of type vehicle, not car. For example, use overtake_vehicle rather than overtake_car.
  • Use lat/lon to name variables of any kind, instead of lateral/longitudinal. For example, use lat_distance rather than lateral_distance.
  • Use speed instead of velocity. For example, use sut_speed rather than sut_velocity.
  • Use acceleration and negative values instead of deceleration. For example, use keep(sut_acceleration in [-2.5..0]mpsps) rather than keep(sut_deceleration in [-2.5..0]mpsps).
OSC2 code: preferred style of naming
# instead of:

scenario top.dut_highway_drive:
    road: highway

scenario top.ego_drive with_cars:
    car1: vehicle    

# prefer:
scenario top.sut_highway_drive:
    road: highway

scenario top.sut_drive with_cars:
    cut_in_vehicle: vehicle

For more information, see:

LINT_CONSTRAINT_SOFT_EQUALS

The LINT_CONSTRAINT_SOFT_EQUALS rule requires the use of default constraints for equality and ‘in’ constraints rather than soft constraints.

OSC2 code: preferred equality constraints
# instead of:
extend top.main:
    max_speed: speed
    keep(soft max_speed == 150kph)
    distance_to_vehicle: length
    keep(soft distance_to_vehicle in [4m..7m])
# prefer:
extend top.main:
    max_speed: speed
    keep(default max_speed == 150kph)
    distance_to_vehicle: length
    keep(default distance_to_vehicle in [4m..7m])