Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add preliminary support for PHP 5.4 #43

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
6 changes: 6 additions & 0 deletions crates/linter/src/plugin/compatibility/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::definition::PluginDefinition;
use crate::plugin::compatibility::rules::php55::finally_feature::FinallyFeatureRule;
use crate::plugin::compatibility::rules::php56::variadic_functions_feature::VariadicFunctionsFeatureRule;
use crate::plugin::compatibility::rules::php74::null_coalesce_assignment_feature::NullCoalesceAssignmentFeatureRule;
use crate::plugin::compatibility::rules::php80::named_arguments_feature::NamedArgumentsFeatureRule;
use crate::plugin::compatibility::rules::php80::promoted_properties_feature::PromotedPropertiesFeatureRule;
Expand All @@ -25,6 +27,10 @@ impl Plugin for CompatibilityPlugin {

fn get_rules(&self) -> Vec<Box<dyn Rule>> {
vec![
// PHP 5.5
Box::new(FinallyFeatureRule),
// PHP 5.6
Box::new(VariadicFunctionsFeatureRule),
// PHP 7.4
Box::new(NullCoalesceAssignmentFeatureRule),
// PHP 8.0
Expand Down
8 changes: 8 additions & 0 deletions crates/linter/src/plugin/compatibility/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
pub mod php55 {
pub mod finally_feature;
}

pub mod php56 {
pub mod variadic_functions_feature;
}

pub mod php74 {
pub mod null_coalesce_assignment_feature;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use indoc::indoc;

use mago_ast::ast::*;
use mago_php_version::PHPVersion;
use mago_reporting::*;
use mago_span::*;
use mago_walker::Walker;

use crate::context::LintContext;
use crate::definition::RuleDefinition;
use crate::definition::RuleUsageExample;
use crate::rule::Rule;

#[derive(Clone, Copy, Debug)]
pub struct FinallyFeatureRule;

impl Rule for FinallyFeatureRule {
fn get_definition(&self) -> RuleDefinition {
RuleDefinition::enabled("Finally Feature", Level::Error)
.with_maximum_supported_php_version(PHPVersion::PHP54)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.with_maximum_supported_php_version(PHPVersion::PHP54)
.with_maximum_supported_php_version(PHPVersion::PHP55)

this has became exlusive now.

.with_description(indoc! {"
Flags any usage of the `finally` keyword, which was introduced in PHP 5.5.

In environments running older versions of PHP, you can use a `try`/`catch` block without a `finally` block instead.
"})
.with_example(RuleUsageExample::valid(
"Using a `try`/`catch` block without a `finally` block",
indoc! {r#"
<?php

try {
// Code that might throw an exception.
} catch (Exception $e) {
// Handle the exception.
}
"#},
))
.with_example(RuleUsageExample::invalid(
"Using a `try`/`catch` block with a `finally` block",
indoc! {r#"
<?php

try {
// Code that might throw an exception.
} catch (Exception $e) {
// Handle the exception.
} finally {
// Code that should always run.
}
"#},
))
}
}

impl<'a> Walker<LintContext<'a>> for FinallyFeatureRule {
fn walk_in_try<'ast>(&self, r#try: &'ast Try, context: &mut LintContext<'a>) {
let Some(finally) = r#try.finally_clause.as_ref() else {
return;
};

let issue = Issue::new(
context.level(),
"The `finally` block is only available in PHP 5.5 and later.",
)
.with_annotation(
Annotation::primary(finally.span()).with_message("Finally block used here."),
);

context.report(issue);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use indoc::indoc;

use mago_ast::ast::*;
use mago_php_version::PHPVersion;
use mago_reporting::*;
use mago_span::*;
use mago_walker::Walker;

use crate::context::LintContext;
use crate::definition::RuleDefinition;
use crate::definition::RuleUsageExample;
use crate::rule::Rule;

#[derive(Clone, Copy, Debug)]
pub struct VariadicFunctionsFeatureRule;

impl Rule for VariadicFunctionsFeatureRule {
fn get_definition(&self) -> RuleDefinition {
RuleDefinition::enabled("Variadic Functions Feature", Level::Error)
.with_maximum_supported_php_version(PHPVersion::PHP55)
.with_description(indoc! {"
Flags any usage of variadic functions, which were introduced in PHP 5.6.

In environments running older versions of PHP, you can use the `func_get_args()` function instead.
"})
.with_example(RuleUsageExample::valid(
"Using `func_get_args()` instead of variadic functions",
indoc! {r#"
<?php

function sum() {
$args = func_get_args();
return array_sum($args);
}

echo sum(1, 2, 3);
"#},
))
.with_example(RuleUsageExample::invalid(
"Using variadic functions",
indoc! {r#"
<?php

function sum(...$args) {
return array_sum($args);
}

echo sum(1, 2, 3);
"#},
))
}
}

impl<'a> Walker<LintContext<'a>> for VariadicFunctionsFeatureRule {
fn walk_in_function<'ast>(&self, function: &'ast Function, context: &mut LintContext<'a>) {
for param in function.parameters.parameters.iter() {
if param.ellipsis.is_none() {
continue;
}

let issue = Issue::new(
context.level(),
"Variadic functions are only available in PHP 5.6 and later.",
)
.with_annotation(
Annotation::primary(param.span()).with_message("Variadic parameter used here."),
)
.with_note("Use `func_get_args()` if you need compatibility with older PHP versions.");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.with_note("Use `func_get_args()` if you need compatibility with older PHP versions.");
.with_help("Use `func_get_args()` if you need compatibility with older PHP versions.");

notes are used to provide more information, help are used to provide a solution, or a workaround.


context.report(issue);
}
}
}
6 changes: 6 additions & 0 deletions crates/php-version/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ pub mod feature;
pub struct PHPVersion(u32);

impl PHPVersion {
/// The PHP 5.4 version.
pub const PHP54: PHPVersion = PHPVersion::new(5, 4, 0);

/// The PHP 5.5 version.
pub const PHP55: PHPVersion = PHPVersion::new(5, 5, 0);

/// The PHP 7.0 version.
pub const PHP70: PHPVersion = PHPVersion::new(7, 0, 0);

Expand Down
2 changes: 1 addition & 1 deletion src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub const MAXIMUM_STACK_SIZE: usize = 256 * 1024 * 1024;
pub const DEFAULT_PHP_VERSION: PHPVersion = PHPVersion::PHP83;

/// The minimum supported PHP version.
pub const MINIMUM_PHP_VERSION: PHPVersion = PHPVersion::PHP74;
pub const MINIMUM_PHP_VERSION: PHPVersion = PHPVersion::PHP54;

/// The maximum supported PHP version.
pub const MAXIMUM_PHP_VERSION: PHPVersion = PHPVersion::PHP84;
Expand Down
Loading