{"@attributes":{"version":"2.0"},"channel":{"title":"DEV Community: Denzyl Dick ","description":"The latest articles on DEV Community by Denzyl Dick  (@denzyldick).","link":"https:\/\/dev.to\/denzyldick","image":{"url":"https:\/\/media2.dev.to\/dynamic\/image\/width=90,height=90,fit=cover,gravity=auto,format=auto\/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F60385%2F7c9cf11a-8c24-410b-85bd-6bb32b93434b.jpeg","title":"DEV Community: Denzyl Dick ","link":"https:\/\/dev.to\/denzyldick"},"language":"en","item":[{"title":"Why is unserializing an object in PHP a bad idea?","pubDate":"Thu, 18 Jul 2024 20:39:42 +0000","link":"https:\/\/dev.to\/denzyldick\/why-is-unserializing-an-object-in-php-a-bad-idea-3odl","guid":"https:\/\/dev.to\/denzyldick\/why-is-unserializing-an-object-in-php-a-bad-idea-3odl","description":"<p>Serializing in PHP is a way of converting a PHP object into a string. This string can be used in various ways, such as storing it in a database or passing it to another function. The PHP documentation says this is handy when passing PHP values around without losing their type and structure. But I have never had that problem before. Maybe I\u2019m not seeing it.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code><span class=\"cp\">&lt;?php<\/span>\n<span class=\"nv\">$test<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">User<\/span><span class=\"p\">();<\/span>\n<span class=\"nv\">$test<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"Denzyl\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">echo<\/span> <span class=\"nb\">serialize<\/span><span class=\"p\">(<\/span><span class=\"nv\">$test<\/span><span class=\"p\">);<\/span>\n<span class=\"c1\">\/\/\/ Output: O:4:\"User\":1:{s:4:\"name\";s:6:\"Denzyl\";}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>So, let's digest the string. The <code>o<\/code> stands for Object, and the following number is the length of the object's name. The two letters  <code>s<\/code> stand for string and the length of the string's name.<br><br>\nWhen you need to convert the string back into PHP, call the <code>unserialize<\/code> function and pass the string as a parameter.<\/p>\n\n<p>When serializing an object, two methods are automagically being called. <code>__serialize()<\/code> &amp; <code>__sleep()<\/code>. This will allow the class author to do something before converting the object into a string.<br>\nThat is straight to the point. But for now, let\u2019s focus on unserializing the string. This means converting the string into a real PHP object that can be later used at runtime in your PHP code.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code><span class=\"cp\">&lt;?php<\/span>\n\n<span class=\"nv\">$string<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'O:8:\"User\":1:{s:4:\"name\";s:6:\"Denzyl\";}'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">echo<\/span> <span class=\"nb\">unserialize<\/span><span class=\"p\">(<\/span><span class=\"nv\">$string<\/span><span class=\"p\">)<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">name<\/span><span class=\"p\">;<\/span>\n<span class=\"c1\">\/\/\/ Output: Denzyl<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The same functionalities also apply to unserializing. But this time, the two methods are <code>__unserialize()<\/code> and <code>__wakeup().<\/code><\/p>\n\n<h3>\n  \n  \n  But why is it a bad idea?\n<\/h3>\n\n<p>Using <code>unserialize<\/code> without knowing it can lead to remote code execution. That's why they say never to trust input. <br>\nLet's say you are lazy and you trust a random input, and you concatenate to the serialized object so you can <br>\nchange a value inside the object. BOOM, you can be hacked.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code><span class=\"cp\">&lt;?php<\/span>\n<span class=\"nv\">$username<\/span> <span class=\"o\">=<\/span> <span class=\"nv\">$_GET<\/span><span class=\"p\">[<\/span><span class=\"s1\">'username'<\/span><span class=\"p\">];<\/span>\n<span class=\"nv\">$serialized<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'O:8:\"User\":1:{s:4:\"name\";s:6:\"'<\/span> <span class=\"mf\">.<\/span> <span class=\"nv\">$username<\/span> <span class=\"mf\">.<\/span> <span class=\"s1\">'\";}'<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>I won't explain how to write an exploit for something like this. Some tools can automatically generate a payload for you, and you can call yourself a script kiddie(we all start somewhere). The one I know is <a href=\"https:\/\/github.com\/ambionics\/phpggc\" rel=\"noopener noreferrer\">PHPGGC<\/a>.<\/p>\n\n<p>To understand the exploit, you can read the OWASP <a href=\"https:\/\/owasp.org\/www-community\/vulnerabilities\/PHP_Object_Injection\" rel=\"noopener noreferrer\">article<\/a>. <br>\nIf you didn't know this before, also read the rest of the OWASP <a href=\"https:\/\/owasp.org\/www-community\/vulnerabilities\/\" rel=\"noopener noreferrer\">articles<\/a> about vulnerabilities<\/p>\n\n<p><em>I know I haven't explained how to write an exploit. I don't think I can do a better job than the articles on the internet. But now you know this, and you can do your research.<\/em><\/p>\n\n<h3>\n  \n  \n  How to prevent being exploited?\n<\/h3>\n\n<p>Why would you want to use this? I do not know; I haven't been programming long enough(~15 years) to have the opportunity to solve a problem using serialize\/unserialize. <br>\nMy solution is too drastic. The simple answer is. <strong>Don't<\/strong> use it in my PHP projects. <\/p>\n\n<p>This article is part of a series of articles in my journey of writing a <a href=\"https:\/\/github.com\/denzyldick\/phanalist\" rel=\"noopener noreferrer\">static analysis<\/a> tool for PHP that can scan massive projects in a couple of minutes\/seconds. And look for rules<br>\nthat the developers want to have in their projects. At the time of writing this article, I'm working on a rule to stop <br>\npeople from using <code>unserialize<\/code>, and it should be ready for the next release. Follow the <a href=\"https:\/\/github.com\/denzyldick\/phanalist\" rel=\"noopener noreferrer\">project<\/a> so that you will get notified when<br>\nI decided to write even more rules. <\/p>\n\n","category":["php","laravel","webdev","beginners"]},{"title":"Improve your CI output.","pubDate":"Sat, 18 May 2024 20:10:54 +0000","link":"https:\/\/dev.to\/denzyldick\/improve-your-ci-output-2eg","guid":"https:\/\/dev.to\/denzyldick\/improve-your-ci-output-2eg","description":"<p>Have you ever been in a situation where you made a PR or MR and waited for a couple of seconds for the output of the CI pipeline? But something went wrong, and you can't see the issue in the blink of an eye. And you get annoyed that you must read a few logs to discover the problem? <\/p>\n\n<p>It's a scenario that many of us have likely encountered at some point.<\/p>\n\n<p>This article teaches how to improve your CI output. I will use Github.<\/p>\n\n<blockquote>\n<p>This article is part of a series about a static analysis tool I've worked on for over a year. It's called <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">Phanalist<\/a>. Please check it out and hit the star button. Thank you.<\/p>\n<\/blockquote>\n\n<p>How can I improve the CI output in Github? When running your CI tools, you probably output everything to STDOUT and view the content in the log viewer.<\/p>\n\n<p>Something like this:<\/p>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6jkmm3hl8flza7socosu.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6jkmm3hl8flza7socosu.png\" alt=\"Image description\" width=\"800\" height=\"365\"><\/a><\/p>\n\n<p>The output format text in Phanalist is not so bad. It's readable because of the table layout. But why stop there? <\/p>\n\n<p>Microsoft is not so evil anymore, and Github has solved that problem I've already. What we will be using is what they call <code>SARIF<\/code>. It stands<br>\nfor Static Analysis Results Interchange Format. It's a specification for understanding the output of static analysis tools. That is how the tools can display information in the code scanning section under the security tab on a repository. <\/p>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzibtgelhhm0kyx8x1yys.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzibtgelhhm0kyx8x1yys.png\" alt=\"Image description\" width=\"800\" height=\"401\"><\/a><\/p>\n\n<p>For Phanalist to have a chance to be adopted by more people, this is a must feature that should be implemented first. Then, I can focus on adding more rules to the tool. <\/p>\n\n<p>For context, <a href=\"https:\/\/gitub.com\/denzyldick\/phanalist\">Phanalist<\/a> consists of rules implemented by the contributors. Every rule has a detailed explanation of what you are doing wrong and guides you in the right direction so you can fix it. <\/p>\n\n<p>The tools under the code scanning section use a Github action called <code>github\/codeql-action\/upload-sarif<\/code>. This action uploads a <code>.sarif<\/code> file to GitHub. Remember that you will need the right permissions to upload a file from the Github workflow. After uploading, Github will validate the file's content, and if there are any errors, they will be displayed in the logs. If everything goes well, you will have more issues to fix under the security tab. <\/p>\n\n<p>The tools you use should have a <code>Sarif<\/code> output. At the time of writing, I do not know if the popular static analysis tools in the PHP ecosystem support Sarif, but if not, you can help them with that. <\/p>\n\n<p>But <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">Phanalist<\/a> supports that format. It can output information in three formats: <code>text<\/code>, <code>json<\/code>, and <code>sarif<\/code>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>phanalist <span class=\"nt\">--src<\/span><span class=\"o\">=<\/span><span class=\"nb\">.<\/span> <span class=\"nt\">--output-format<\/span><span class=\"o\">=<\/span>sarif\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The output will be something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight json\"><code><span class=\"p\">{<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"version\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"2.1.0\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"$schema\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"http:\/\/json.schemastore.org\/sarif-2.1.0-rtm.4\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n  <\/span><span class=\"nl\">\"runs\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"w\">\n    <\/span><span class=\"p\">{<\/span><span class=\"w\">\n      <\/span><span class=\"nl\">\"tool\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n        <\/span><span class=\"nl\">\"driver\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"name\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"Phanalist\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"informationUri\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"https:\/\/github.com\/denzyldick\/phanalist\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"rules\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"w\">\n            <\/span><span class=\"p\">{<\/span><span class=\"w\">\n              <\/span><span class=\"nl\">\"id\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"e0009\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n              <\/span><span class=\"nl\">\"shortDescription\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n                <\/span><span class=\"nl\">\"text\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"Method is too complex\"<\/span><span class=\"w\">\n              <\/span><span class=\"p\">},<\/span><span class=\"w\">\n              <\/span><span class=\"nl\">\"properties\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n                <\/span><span class=\"nl\">\"category\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"phanalist\"<\/span><span class=\"w\">\n              <\/span><span class=\"p\">}<\/span><span class=\"w\">\n            <\/span><span class=\"p\">}<\/span><span class=\"w\">\n          <\/span><span class=\"p\">]<\/span><span class=\"w\">\n        <\/span><span class=\"p\">}<\/span><span class=\"w\">\n      <\/span><span class=\"p\">},<\/span><span class=\"w\">\n      <\/span><span class=\"nl\">\"artifacts\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"w\">\n        <\/span><span class=\"p\">{<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"location\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n            <\/span><span class=\"nl\">\"uri\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"src\/complex.php\"<\/span><span class=\"w\">\n          <\/span><span class=\"p\">}<\/span><span class=\"w\">\n        <\/span><span class=\"p\">}<\/span><span class=\"w\">\n      <\/span><span class=\"p\">],<\/span><span class=\"w\">\n      <\/span><span class=\"nl\">\"results\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"w\">\n        <\/span><span class=\"p\">{<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"level\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"warning\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"message\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n            <\/span><span class=\"nl\">\"text\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"Method is too complex.\"<\/span><span class=\"w\">\n          <\/span><span class=\"p\">},<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"locations\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"w\">\n            <\/span><span class=\"p\">{<\/span><span class=\"w\">\n              <\/span><span class=\"nl\">\"physicalLocation\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n                <\/span><span class=\"nl\">\"artifactLocation\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n                  <\/span><span class=\"nl\">\"uri\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"src\/complex.php\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n                  <\/span><span class=\"nl\">\"index\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\">\n                <\/span><span class=\"p\">},<\/span><span class=\"w\">\n                <\/span><span class=\"nl\">\"region\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\">\n                  <\/span><span class=\"nl\">\"startLine\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"w\">\n                  <\/span><span class=\"nl\">\"startColumn\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mi\">5<\/span><span class=\"w\">\n                <\/span><span class=\"p\">}<\/span><span class=\"w\">\n              <\/span><span class=\"p\">}<\/span><span class=\"w\">\n            <\/span><span class=\"p\">}<\/span><span class=\"w\">\n          <\/span><span class=\"p\">],<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"ruleId\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"no-unused-vars\"<\/span><span class=\"p\">,<\/span><span class=\"w\">\n          <\/span><span class=\"nl\">\"ruleIndex\"<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\">\n        <\/span><span class=\"p\">}<\/span><span class=\"w\">\n      <\/span><span class=\"p\">]<\/span><span class=\"w\">\n    <\/span><span class=\"p\">}<\/span><span class=\"w\">\n  <\/span><span class=\"p\">]<\/span><span class=\"w\">\n<\/span><span class=\"p\">}<\/span><span class=\"w\">\n<\/span><\/code><\/pre>\n\n<\/div>\n\n\n\n<p>I won't explain Sarif in detail in this article; the people behind it have already done an excellent job.<\/p>\n\n<p>The next step is to upload this output to Github using the <code>github\/codeql-action\/upload-sarif<\/code>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">on<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">push<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">branches<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">main\"<\/span>\n<span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Sarif<\/span>\n<span class=\"na\">jobs<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">upload-sarif<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">runs-on<\/span><span class=\"pi\">:<\/span> <span class=\"s\">ubuntu-latest<\/span>\n    <span class=\"na\">steps<\/span><span class=\"pi\">:<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions\/checkout@v4<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Install Rust toolchain<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">actions-rs\/toolchain@v1.0.6<\/span> <span class=\"c1\">#@v1<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">profile<\/span><span class=\"pi\">:<\/span> <span class=\"s\">minimal<\/span>\n          <span class=\"na\">toolchain<\/span><span class=\"pi\">:<\/span> <span class=\"s\">stable<\/span>\n          <span class=\"na\">override<\/span><span class=\"pi\">:<\/span> <span class=\"kc\">true<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">run<\/span><span class=\"pi\">:<\/span> <span class=\"s\">cargo run --release -- --src=. --output-format=sarif | tee results.sarif<\/span>\n      <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">Upload SARIF file<\/span>\n        <span class=\"na\">uses<\/span><span class=\"pi\">:<\/span> <span class=\"s\">github\/codeql-action\/upload-sarif@v3<\/span>\n        <span class=\"na\">with<\/span><span class=\"pi\">:<\/span>\n          <span class=\"na\">sarif_file<\/span><span class=\"pi\">:<\/span> <span class=\"s\">results.sarif<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After executing this workflow, the result will be displayed in the security tab under code scanning. <\/p>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmo3430915c3cossaims.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmo3430915c3cossaims.png\" alt=\"Code scanning\" width=\"800\" height=\"423\"><\/a><\/p>\n\n<p>The rules in Phanalist also consist of detailed explanations written in Markdown, which are backed into the executable binary. This comes in very handy when scanning code. In <code>Sarif,<\/code> you can specify a Markdown for the result found when you ran your tool.<\/p>\n\n<p>If I click and open one of the warnings, I will be greeted with a detailed explanation. Including the file and location that is causing the issue.  <\/p>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxj6yxra96lf87w4a0pzq.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxj6yxra96lf87w4a0pzq.png\" alt=\"Detailed explanation\" width=\"800\" height=\"495\"><\/a><\/p>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75rajcv2fob5chr3xbim.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75rajcv2fob5chr3xbim.png\" alt=\"Detailed explanation\" width=\"800\" height=\"567\"><\/a><\/p>\n\n<p>I hope you learned something useful and can now improve your CI output. <\/p>\n\n","category":["php","opensource","codequality"]},{"title":"How I made it impossible to write spaghetti code. Part 2","pubDate":"Mon, 22 Jan 2024 18:33:00 +0000","link":"https:\/\/dev.to\/denzyldick\/traversing-an-ast-of-php-source-code-2kee","guid":"https:\/\/dev.to\/denzyldick\/traversing-an-ast-of-php-source-code-2kee","description":"<blockquote>\n<p>This is the part(3) of a series. I suggest you read parts <a href=\"https:\/\/dev.to\/denzyldick\/the-beginning-of-my-php-static-analyzer-in-rust-5bp8\">1<\/a> and <a href=\"https:\/\/dev.to\/denzyldick\/how-i-made-it-impossible-to-write-spaghetti-code-dg4\">2<\/a> before this one. <\/p>\n<\/blockquote>\n\n<p>In part <a href=\"https:\/\/dev.to\/denzyldick\/how-i-made-it-impossible-to-write-spaghetti-code-dg4\">2<\/a>, I made sure that the test passed correctly. The focus now is how we traverse a block of code inside its scope. We should be able to increase the variables in the formula at the right moment. <\/p>\n\n<p>If you have read part <a href=\"https:\/\/dev.to\/denzyldick\/the-beginning-of-my-php-static-analyzer-in-rust-5bp8\">1<\/a>, you know that we need to implement the validate function that is mandatory in the trait <code>Rule<\/code>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code>\n<span class=\"k\">impl<\/span> <span class=\"n\">Rule<\/span> <span class=\"k\">for<\/span> <span class=\"n\">E009<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">fn<\/span> <span class=\"nf\">validate<\/span><span class=\"p\">(<\/span>\n        <span class=\"o\">&amp;<\/span><span class=\"k\">self<\/span><span class=\"p\">,<\/span>\n        <span class=\"n\">statement<\/span><span class=\"p\">:<\/span> <span class=\"o\">&amp;<\/span><span class=\"nn\">php_parser_rs<\/span><span class=\"p\">::<\/span><span class=\"nn\">parser<\/span><span class=\"p\">::<\/span><span class=\"nn\">ast<\/span><span class=\"p\">::<\/span><span class=\"n\">Statement<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">)<\/span> <span class=\"k\">-&gt;<\/span> <span class=\"nb\">Vec<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">crate<\/span><span class=\"p\">::<\/span><span class=\"nn\">project<\/span><span class=\"p\">::<\/span><span class=\"n\">Suggestion<\/span><span class=\"o\">&gt;<\/span> <span class=\"p\">{<\/span>\n\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>In part <a href=\"https:\/\/dev.to\/denzyldick\/how-i-made-it-impossible-to-write-spaghetti-code-dg4\">2<\/a> we have learned that :<\/p>\n\n<blockquote>\n<p>Nodes are like the conditional statement: if, else, while, for, etc.<br>\nEdges are the paths that can be taken. <\/p>\n<\/blockquote>\n\n<p>The <code>validate<\/code> function will be executed for every statement in a source code. In the source code below, there are 32 lines of code.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code><span class=\"cp\">&lt;?php<\/span>\n\n<span class=\"kd\">class<\/span> <span class=\"nc\">Index<\/span><span class=\"p\">{<\/span>\n\n  <span class=\"k\">public<\/span> <span class=\"k\">function<\/span> <span class=\"n\">tooComplex<\/span><span class=\"p\">(){<\/span>\n    <span class=\"nv\">$a<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span><span class=\"p\">;<\/span>\n    <span class=\"nv\">$b<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">2<\/span><span class=\"p\">;<\/span>\n\n\n    <span class=\"k\">if<\/span><span class=\"p\">(<\/span><span class=\"nv\">$a<\/span> <span class=\"o\">&gt;<\/span> <span class=\"nv\">$b<\/span><span class=\"p\">){<\/span>\n      <span class=\"k\">if<\/span><span class=\"p\">(<\/span><span class=\"nv\">$b<\/span> <span class=\"o\">&lt;<\/span> <span class=\"nv\">$a<\/span><span class=\"p\">){<\/span>\n\n        <span class=\"k\">if<\/span><span class=\"p\">(<\/span><span class=\"nv\">$a<\/span> <span class=\"o\">==<\/span> <span class=\"nv\">$b<\/span><span class=\"p\">){<\/span>\n\n          <span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"nv\">$b<\/span> <span class=\"o\">&gt;<\/span> <span class=\"nv\">$a<\/span><span class=\"p\">){<\/span>\n\n          <span class=\"p\">}<\/span>\n\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p><a href=\"https:\/\/github.com\/denzyldick\/phanalist\">Phanalist<\/a> needs a way to detect when we are in the function's scope with the name <code>tooComplex().<\/code> With pattern matching, it is super easy to detect if the statement is either: <code>if<\/code>,<code>else<\/code>,<code>etc..<\/code> The first statement that I want to match for is <code>class Index{<\/code> and from there, we will continue down the tree. If you think the same way as I do you know that I will be using recursion to calculate the cyclomatic complexity. After we have matched the scope of the <code>tooComplex()<\/code> function.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code><span class=\"k\">impl<\/span> <span class=\"n\">Rule<\/span> <span class=\"k\">for<\/span> <span class=\"n\">E009<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">fn<\/span> <span class=\"nf\">validate<\/span><span class=\"p\">(<\/span>\n        <span class=\"o\">&amp;<\/span><span class=\"k\">self<\/span><span class=\"p\">,<\/span>\n        <span class=\"n\">statement<\/span><span class=\"p\">:<\/span> <span class=\"o\">&amp;<\/span><span class=\"nn\">php_parser_rs<\/span><span class=\"p\">::<\/span><span class=\"nn\">parser<\/span><span class=\"p\">::<\/span><span class=\"nn\">ast<\/span><span class=\"p\">::<\/span><span class=\"n\">Statement<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">)<\/span> <span class=\"k\">-&gt;<\/span> <span class=\"nb\">Vec<\/span><span class=\"o\">&lt;<\/span><span class=\"k\">crate<\/span><span class=\"p\">::<\/span><span class=\"nn\">project<\/span><span class=\"p\">::<\/span><span class=\"n\">Suggestion<\/span><span class=\"o\">&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">let<\/span> <span class=\"k\">mut<\/span> <span class=\"n\">suggestions<\/span> <span class=\"o\">=<\/span> <span class=\"nn\">Vec<\/span><span class=\"p\">::<\/span><span class=\"nf\">new<\/span><span class=\"p\">();<\/span>\n        <span class=\"k\">let<\/span> <span class=\"k\">mut<\/span> <span class=\"n\">graph<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Graph<\/span> <span class=\"p\">{<\/span> <span class=\"n\">n<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"n\">e<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"n\">p<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">};<\/span>\n        <span class=\"k\">match<\/span> <span class=\"n\">statement<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nn\">Statement<\/span><span class=\"p\">::<\/span><span class=\"nf\">Class<\/span><span class=\"p\">(<\/span><span class=\"n\">class<\/span><span class=\"p\">)<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"p\">{<\/span>\n                <span class=\"k\">for<\/span> <span class=\"n\">member<\/span> <span class=\"k\">in<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">class<\/span><span class=\"py\">.body.members<\/span> <span class=\"p\">{<\/span>\n                    <span class=\"k\">match<\/span> <span class=\"n\">member<\/span> <span class=\"p\">{<\/span>\n                        <span class=\"nn\">ClassMember<\/span><span class=\"p\">::<\/span><span class=\"nf\">ConcreteMethod<\/span><span class=\"p\">(<\/span><span class=\"n\">concretemethod<\/span><span class=\"p\">)<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"p\">{<\/span>\n                            <span class=\"k\">match<\/span> <span class=\"n\">concretemethod<\/span><span class=\"py\">.body<\/span><span class=\"nf\">.clone<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n                                <span class=\"n\">MethodBody<\/span> <span class=\"p\">{<\/span>\n                                    <span class=\"n\">comments<\/span><span class=\"p\">:<\/span> <span class=\"n\">_<\/span><span class=\"p\">,<\/span>\n                                    <span class=\"n\">left_brace<\/span><span class=\"p\">:<\/span> <span class=\"n\">_<\/span><span class=\"p\">,<\/span>\n                                    <span class=\"n\">statements<\/span><span class=\"p\">,<\/span>\n                                    <span class=\"n\">right_brace<\/span><span class=\"p\">:<\/span> <span class=\"n\">_<\/span><span class=\"p\">,<\/span>\n                                <span class=\"p\">}<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"p\">{<\/span>\n                                   <span class=\"cd\">\/\/\/ HERE !!<\/span>\n                                    <span class=\"p\">}<\/span>\n                                <span class=\"p\">}<\/span>\n                            <span class=\"p\">}<\/span>\n                        <span class=\"p\">}<\/span>\n                        <span class=\"n\">_<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"p\">{}<\/span>\n                    <span class=\"p\">}<\/span>\n                <span class=\"p\">}<\/span>\n            <span class=\"p\">}<\/span>\n            <span class=\"n\">_<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"p\">{}<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"n\">suggestions<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>If you aren't familiar with pattern matching, it's kind of a switch keyword on steroids. Look for the                                Look for <code>\/\/\/ HERE !!<\/code> in the above code.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code> <span class=\"n\">MethodBody<\/span> <span class=\"p\">{<\/span>\n                                    <span class=\"n\">comments<\/span><span class=\"p\">:<\/span> <span class=\"n\">_<\/span><span class=\"p\">,<\/span>\n                                    <span class=\"n\">left_brace<\/span><span class=\"p\">:<\/span> <span class=\"n\">_<\/span><span class=\"p\">,<\/span>\n                                    <span class=\"n\">statements<\/span><span class=\"p\">,<\/span>\n                                    <span class=\"n\">right_brace<\/span><span class=\"p\">:<\/span> <span class=\"n\">_<\/span><span class=\"p\">,<\/span>\n                                <span class=\"p\">}<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"p\">{<\/span>\n                                    <span class=\"cd\">\/\/\/ HERE 1<\/span>\n\n                                    <span class=\"p\">}<\/span>\n                                <span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>As you can see we have four parameters that we can use. The ones we are looking for are the statements. The type of this parameter is <code>Vec&lt;Statement&gt;<\/code> meaning it can be anything.<\/p>\n\n<p>Let's use the <code>Graph<\/code> we previously created in part <a href=\"https:\/\/dev.to\/denzyldick\/how-i-made-it-impossible-to-write-spaghetti-code-dg4\">2<\/a><\/p>\n\n<p>In the source code below, <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">Phanalist<\/a> calls a function with <code>let graph  = calculate _cyclomatic_complexity();<\/code> This function will return a struct of the type <code>Graph<\/code>. The first parameter passed is <code>statements.clone()<\/code>. This function uses recursion to traverse down the tree. In part 4 I will explain the recursion we were thinking about.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code>\n <span class=\"k\">let<\/span> <span class=\"n\">graph<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">calculate_cyclomatic_complexity<\/span><span class=\"p\">(<\/span>\n                                        <span class=\"n\">statements<\/span><span class=\"nf\">.clone<\/span><span class=\"p\">(),<\/span>\n                                        <span class=\"o\">&amp;<\/span><span class=\"k\">mut<\/span> <span class=\"n\">graph<\/span><span class=\"p\">,<\/span>\n                                    <span class=\"p\">);<\/span>\n <span class=\"k\">if<\/span> <span class=\"n\">graph<\/span><span class=\"nf\">.calculate<\/span><span class=\"p\">()<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">10<\/span> <span class=\"p\">{<\/span>\n<span class=\"n\">suggestions<\/span><span class=\"nf\">.push<\/span><span class=\"p\">(<\/span><span class=\"nn\">Suggestion<\/span><span class=\"p\">::<\/span><span class=\"nf\">from<\/span><span class=\"p\">(<\/span><span class=\"s\">\"This method body is too complex. Make it easier to understand.\"<\/span><span class=\"nf\">.to_string<\/span><span class=\"p\">(),<\/span>\n                <span class=\"n\">concretemethod<\/span><span class=\"py\">.function<\/span><span class=\"p\">,<\/span>\n<span class=\"s\">\"E009\"<\/span><span class=\"nf\">.to_string<\/span><span class=\"p\">()<\/span> <span class=\"p\">));<\/span>\n<span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The <code>Graph<\/code> struct has the <code>calculate<\/code> function we previously used to calculate the cyclomatic complexity. My threshold is always ten, so I will be using that.<\/p>\n\n<p>If the value exceeds ten, I push the <code>Suggestion<\/code> onto the vector. The vector of <code>Suggestion<\/code> is the value returned to the validate function's caller. <\/p>\n\n<h1>\n  \n  \n  Recursion\n<\/h1>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwj5yh9nh4jtfjnie3ncf.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwj5yh9nh4jtfjnie3ncf.png\" alt=\"Image description\" width=\"287\" height=\"176\"><\/a><\/p>\n\n<blockquote>\n<p>In computer science, recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems using functions that call themselves from within their code. <a href=\"https:\/\/en.wikipedia.org\/wiki\/Recursion_(computer_science)\">Wikipedia<\/a><\/p>\n<\/blockquote>\n\n<h1>\n  \n  \n  Conclusion\n<\/h1>\n\n<p>If you are a PHP developer, you know that a developer can make many more mistakes in PHP. In the future, the list of Rules will continue to grow into something more useful.<\/p>\n\n<p>Thanks for reading!<\/p>\n\n<p>Contribution is always welcome if you have a mistake you would like to add to <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">Phanalist<\/a>.<\/p>\n\n","category":["codequality","php","webdev","beginners"]},{"title":"How I made it impossible to write spaghetti code.","pubDate":"Sun, 21 Jan 2024 00:48:50 +0000","link":"https:\/\/dev.to\/denzyldick\/how-i-made-it-impossible-to-write-spaghetti-code-dg4","guid":"https:\/\/dev.to\/denzyldick\/how-i-made-it-impossible-to-write-spaghetti-code-dg4","description":"<blockquote>\n<p>This is part 2 of a series of my static analyzer for PHP. If you did not read part <a href=\"https:\/\/dev.to\/denzyldick\/the-beginning-of-my-php-static-analyzer-in-rust-5bp8\">1<\/a>, I suggest you to read it first. <\/p>\n<\/blockquote>\n\n<p>A long time ago, I went to a development user group, and one of the talks was about cyclomatic complexity. At that time, I thought, what a cool name. If you already know the meaning of that cool name. Congrats, you are probably 1 of those developers who can detect lousy code without reading it. By seeing the indentation's shape, you can smell the bad code. <br>\n<a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo1n1vk543d8cz6ftb64.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feo1n1vk543d8cz6ftb64.png\" alt=\"Bad code with too many identatio\" width=\"720\" height=\"511\"><\/a><\/p>\n\n<p><em><strong>Cyclomatic definition:<\/strong><br>\nUsed to describe the number of circuits in a network; equal to the number of edges minus the number of nodes plus the number of graphs.<\/em><\/p>\n\n<p>Ok, breathe. If we translate the definitions into code, it will be something like this. <\/p>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugeaorf0204fpyhyuq6a.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugeaorf0204fpyhyuq6a.png\" alt=\"Bad code example\" width=\"800\" height=\"594\"><\/a><\/p>\n\n<p>Nodes are like the conditional statement: <code>if<\/code>, <code>else<\/code>, <code>while<\/code>, <code>for<\/code>, etc.<br>\nEdges are the paths that can be taken. There are two paths in the code on lines <code>4<\/code> and <code>14<\/code>. One of the two can be taken if the variable defined on line <code>3<\/code> has the value of <code>Hola<\/code>; in this case, the first path will be taken. But in this example, the value of the <code>$a<\/code> is <code>Helloworld<\/code> so the second path will be taken. In the control flow graph below, you can view a better representation.<\/p>\n\n<p><a href=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feehbcsl5fsphsjk3klw2.png\" class=\"article-body-image-wrapper\"><img src=\"https:\/\/media.dev.to\/cdn-cgi\/image\/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto\/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feehbcsl5fsphsjk3klw2.png\" alt=\"Control flow graph\" width=\"800\" height=\"787\"><\/a><\/p>\n\n<p>Ok, right; what is the complexity of that cool name I previously told you about? <\/p>\n\n<p>The code above is a small example, but imagine you have a method that has 100 lines of code. Then, the complexity of the code will increase drastically.<\/p>\n<h2>\n  \n  \n  Calculate the complexity\n<\/h2>\n\n<p>The equation for calculating the cyclomatic complexity is: <\/p>\n\n<p>\n\n<\/p>\n<div class=\"katex-element\">\n  <span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\">M=N\u2212E+2PM = N - E + 2P <\/span><span class=\"katex-html\"><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord mathnormal\">M<\/span><span class=\"mspace\"><\/span><span class=\"mrel\">=<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord mathnormal\">N<\/span><span class=\"mspace\"><\/span><span class=\"mbin\">\u2212<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord mathnormal\">E<\/span><span class=\"mspace\"><\/span><span class=\"mbin\">+<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord\">2<\/span><span class=\"mord mathnormal\">P<\/span><\/span><\/span><\/span><\/span>\n<\/div>\n\n\n<blockquote>\n<p>This formula is also known as McCabe's Cyclomatic Complexity (MCC) and is widely used to measure the complexity of a program by analyzing its control flow structure.<\/p>\n<\/blockquote>\n\n<p><code>N<\/code> stands for the number of nodes, and <code>E<\/code> stands for the number of edges. The <code>2P<\/code> stands for two multiplied by the number of exit nodes. In our example, this will translate into: <\/p>\n\n\n<div class=\"katex-element\">\n  <span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\">5=8\u22129+2x35 = 8 - 9 + 2 x 3 <\/span><span class=\"katex-html\"><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord\">5<\/span><span class=\"mspace\"><\/span><span class=\"mrel\">=<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord\">8<\/span><span class=\"mspace\"><\/span><span class=\"mbin\">\u2212<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord\">9<\/span><span class=\"mspace\"><\/span><span class=\"mbin\">+<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord\">2<\/span><span class=\"mord mathnormal\">x<\/span><span class=\"mord\">3<\/span><\/span><\/span><\/span><\/span>\n<\/div>\n\n\n<p>So, I started this blog by saying I can prevent myself from writing spaghetti code. If you did not read part <a href=\"https:\/\/dev.to\/denzyldick\/the-beginning-of-my-php-static-analyzer-in-rust-5bp8\">1<\/a> of this series, you might not know I'm working on a static analyzer for PHP. The project's name is phanalist, and it's available on <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">github<\/a>. <\/p>\n\n<p>In the following paragraph, we will see how <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">phanalist<\/a> can calculate the cyclomatic complexity of the scope of a method. Before creating Phanalist, I always kept the cyclomatic complexity of the methods I wrote in my mind. And if I see that the complexity is higher than 10. I always try to refactor the method, making it easier to understand. <\/p>\n\n<p>How does <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">phanalist<\/a> calculate the cyclomatic complexity? Let's start by implementing the equation above. We will start by creating a struct named Graph. This struct will have the three variables from the equation(n, e, and p).<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code><span class=\"k\">struct<\/span> <span class=\"n\">Graph<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">n<\/span><span class=\"p\">:<\/span> <span class=\"nb\">i64<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">e<\/span><span class=\"p\">:<\/span> <span class=\"nb\">i64<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">p<\/span><span class=\"p\">:<\/span> <span class=\"nb\">i64<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n<blockquote>\n<p>This struct will be passed around when traversing the abstract syntax tree.<\/p>\n<\/blockquote>\n\n\n<div class=\"katex-element\">\n  <span class=\"katex-display\"><span class=\"katex\"><span class=\"katex-mathml\">M=N\u2212E+2PM = N - E + 2P <\/span><span class=\"katex-html\"><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord mathnormal\">M<\/span><span class=\"mspace\"><\/span><span class=\"mrel\">=<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord mathnormal\">N<\/span><span class=\"mspace\"><\/span><span class=\"mbin\">\u2212<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord mathnormal\">E<\/span><span class=\"mspace\"><\/span><span class=\"mbin\">+<\/span><span class=\"mspace\"><\/span><\/span><span class=\"base\"><span class=\"strut\"><\/span><span class=\"mord\">2<\/span><span class=\"mord mathnormal\">P<\/span><\/span><\/span><\/span><\/span>\n<\/div>\n\n\n\n<p>When traversing the AST, we can increase the variables at the right moment. After that, I used the MCC equation to calculate the cyclomatic complexity of our example code.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code><span class=\"k\">impl<\/span> <span class=\"n\">Graph<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">pub<\/span> <span class=\"k\">fn<\/span> <span class=\"nf\">calculate<\/span><span class=\"p\">(<\/span><span class=\"k\">self<\/span><span class=\"p\">)<\/span> <span class=\"k\">-&gt;<\/span> <span class=\"nb\">i64<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">self<\/span><span class=\"py\">.n<\/span> <span class=\"o\">-<\/span> <span class=\"k\">self<\/span><span class=\"py\">.e<\/span> <span class=\"o\">+<\/span> <span class=\"p\">(<\/span><span class=\"mi\">2<\/span> <span class=\"o\">*<\/span> <span class=\"k\">self<\/span><span class=\"py\">.p<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"nd\">#[test]<\/span>\n<span class=\"k\">pub<\/span> <span class=\"k\">fn<\/span> <span class=\"nf\">calculate<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">let<\/span> <span class=\"n\">g<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Graph<\/span> <span class=\"p\">{<\/span> <span class=\"n\">n<\/span><span class=\"p\">:<\/span> <span class=\"mi\">8<\/span><span class=\"p\">,<\/span> <span class=\"n\">e<\/span><span class=\"p\">:<\/span> <span class=\"mi\">9<\/span><span class=\"p\">,<\/span> <span class=\"n\">p<\/span><span class=\"p\">:<\/span> <span class=\"mi\">3<\/span> <span class=\"p\">};<\/span>\n    <span class=\"nd\">assert_eq!<\/span><span class=\"p\">(<\/span><span class=\"n\">g<\/span><span class=\"nf\">.calculate<\/span><span class=\"p\">(),<\/span> <span class=\"mi\">5<\/span><span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>In part <a href=\"https:\/\/dev.to\/denzyldick\/the-beginning-of-my-php-static-analyzer-in-rust-5bp8\">1<\/a>, I explained how to navigate the abstract syntax tree and how Phanalist generates one. If you missed it, I suggest you read that before reading the next part of the series.<\/p>\n\n<p>In part <a href=\"https:\/\/dev.to\/denzyldick\/traversing-an-ast-of-php-source-code-2kee\">3<\/a> of this series. I will explain how we traverse the AST when calculating the cyclomatic complexity. <\/p>\n\n","category":["php","rust","webdev","beginners"]},{"title":"Write your own static analyzer for PHP.","pubDate":"Sat, 18 Feb 2023 11:44:35 +0000","link":"https:\/\/dev.to\/denzyldick\/the-beginning-of-my-php-static-analyzer-in-rust-5bp8","guid":"https:\/\/dev.to\/denzyldick\/the-beginning-of-my-php-static-analyzer-in-rust-5bp8","description":"<p>I keep reading everywhere that rust is fast, has memory safety guardrails, and is 1 of the most loved languages lately. After reading the book and dreaming about understanding the language, I decided to build a static analyzer for the language I've been using for over a decade. I will be naming it <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">Phanalist<\/a> and the code will also be available on <br>\n<a href=\"https:\/\/dev.togithub\">https:\/\/github.com\/denzyldick\/phanalist<\/a>. <\/p>\n\n<p>To see if this idea would work, I made a list of 4 common bad practices\/mistakes I often see. As you can see in the code below, we can all agree that the class doesn't make you happy.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code> <span class=\"cp\">&lt;?php<\/span>\n\n <span class=\"kd\">class<\/span> <span class=\"nc\">uTesting<\/span> <span class=\"kd\">extends<\/span> <span class=\"nc\">FakeClass<\/span>\n  <span class=\"p\">{<\/span>\n    <span class=\"k\">const<\/span> <span class=\"no\">I_<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">const<\/span> <span class=\"no\">hello<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"nv\">$no_<\/span><span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">,<\/span> <span class=\"nv\">$no_modifier<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">public<\/span> <span class=\"k\">function<\/span> <span class=\"n\">__construct<\/span><span class=\"p\">(<\/span><span class=\"nv\">$o<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n      <span class=\"nv\">$this<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">fake_variable<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'hellworld'<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">function<\/span> <span class=\"n\">test<\/span><span class=\"p\">(<\/span><span class=\"nv\">$a<\/span><span class=\"p\">){<\/span>\n      <span class=\"k\">return<\/span> <span class=\"mi\">1<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To keep it easy, I will first find these four common mistakes that are easy to spot. This list will continue to grow in the future. <\/p>\n\n<ul>\n<li>Misplaced opening tag.<\/li>\n<li>Class name that starts in lowercase<\/li>\n<li>Lowercase constants<\/li>\n<li>Defining parameters without a type.<\/li>\n<\/ul>\n\n<p>The static analyzer should be beginner friendly. Instead of making the developer's life harder, it should be able to explain the error in a way that the developer should understand. But first, let us focus on the first steps.<\/p>\n\n<p>I will use <code>PHP-Parser<\/code> a rust library that can parse PHP code and generate an AST(abstract syntax tree). The parser's output for the PHP code above will be a vector(<code>Vec&lt;Statement<\/code>) containing all the statements.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>   [\n    FullOpeningTag(\n        Span {\n            line: 1,\n            column: 1,\n            position: 0,\n        },\n    ),\n    Class(\n        ClassStatement {\n            attributes: [],\n            modifiers: ClassModifierGroup {\n                modifiers: [],\n            },\n            class: Span {\n                line: 2,\n                column: 2,\n                position: 7,\n            },\n            name: SimpleIdentifier {\n                span: Span {\n                    line: 2,\n                    column: 8,\n                    position: 13,\n                },\n                value: \"uTesting\",\n            },\n            extends: Some(\n                ClassExtends {\n                    extends: Span {\n                        line: 2,\n                        column: 17,\n                        position: 22,\n                    },\n                    parent: SimpleIdentifier {\n                        span: Span {\n                            line: 2,\n                            column: 25,\n                            position: 30,\n                        },\n                        value: \"FakeClass\",\n                    },\n                },\n            ),\n            implements: None,\n            body: ClassBody {\n                left_brace: Span {\n                    line: 3,\n                    column: 3,\n                    position: 42,\n                },\n                members: [\n                    Constant(\n                        ClassishConstant {\n                            comments: CommentGroup {\n                                comments: [],\n                            },\n                            attributes: [],\n                            modifiers: ConstantModifierGroup {\n                                modifiers: [],\n                            },\n                            const: Span {\n                                line: 4,\n                                column: 5,\n                                position: 48,\n                            },\n                            entries: [\n                                ConstantEntry {\n                                    name: SimpleIdentifier {\n                                        span: Span {\n                                            line: 4,\n                                            column: 11,\n                                            position: 54,\n                                        },\n                                        value: \"I_\",\n                                    },\n                                    equals: Span {\n                                        line: 4,\n                                        column: 14,\n                                        position: 57,\n                                    },\n                                    value: Null,\n                                },\n                            ],\n                            semicolon: Span {\n                                line: 4,\n                                column: 20,\n                                position: 63,\n                            },\n                        },\n                    ),\n                    Constant(\n                        ClassishConstant {\n                            comments: CommentGroup {\n                                comments: [],\n                            },\n                            attributes: [],\n                            modifiers: ConstantModifierGroup {\n                                modifiers: [],\n                            },\n                            const: Span {\n                                line: 5,\n                                column: 5,\n                                position: 69,\n                            },\n                            entries: [\n                                ConstantEntry {\n                                    name: SimpleIdentifier {\n                                        span: Span {\n                                            line: 5,\n                                            column: 11,\n                                            position: 75,\n                                        },\n                                        value: \"hello\",\n                                    },\n                                    equals: Span {\n                                        line: 5,\n                                        column: 17,\n                                        position: 81,\n                                    },\n                                    value: Null,\n                                },\n                            ],\n                            semicolon: Span {\n                                line: 5,\n                                column: 23,\n                                position: 87,\n                            },\n                        },\n                    ),\n                    Property(\n                        Property {\n                            attributes: [],\n                            modifiers: PropertyModifierGroup {\n                                modifiers: [],\n                            },\n                            type: None,\n                            entries: [\n                                Initialized {\n                                    variable: SimpleVariable {\n                                        span: Span {\n                                            line: 6,\n                                            column: 5,\n                                            position: 93,\n                                        },\n                                        name: \"$no_\",\n                                    },\n                                    equals: Span {\n                                        line: 6,\n                                        column: 9,\n                                        position: 97,\n                                    },\n                                    value: Null,\n                                },\n                                Initialized {\n                                    variable: SimpleVariable {\n                                        span: Span {\n                                            line: 6,\n                                            column: 17,\n                                            position: 105,\n                                        },\n                                        name: \"$no_modifier\",\n                                    },\n                                    equals: Span {\n                                        line: 6,\n                                        column: 30,\n                                        position: 118,\n                                    },\n                                    value: Null,\n                                },\n                            ],\n                            end: Span {\n                                line: 6,\n                                column: 36,\n                                position: 124,\n                            },\n                        },\n                    ),\n                    ConcreteConstructor(\n                        ConcreteConstructor {\n                            comments: CommentGroup {\n                                comments: [],\n                            },\n                            attributes: [],\n                            modifiers: MethodModifierGroup {\n                                modifiers: [\n                                    Public(\n                                        Span {\n                                            line: 8,\n                                            column: 5,\n                                            position: 131,\n                                        },\n                                    ),\n                                ],\n                            },\n                            function: Span {\n                                line: 8,\n                                column: 12,\n                                position: 138,\n                            },\n                            ampersand: None,\n                            name: SimpleIdentifier {\n                                span: Span {\n                                    line: 8,\n                                    column: 21,\n                                    position: 147,\n                                },\n                                value: \"__construct\",\n                            },\n                            parameters: ConstructorParameterList {\n                                comments: CommentGroup {\n                                    comments: [],\n                                },\n                                left_parenthesis: Span {\n                                    line: 8,\n                                    column: 32,\n                                    position: 158,\n                                },\n                                parameters: CommaSeparated {\n                                    inner: [\n                                        ConstructorParameter {\n                                            attributes: [],\n                                            comments: CommentGroup {\n                                                comments: [],\n                                            },\n                                            ampersand: None,\n                                            name: SimpleVariable {\n                                                span: Span {\n                                                    line: 8,\n                                                    column: 33,\n                                                    position: 159,\n                                                },\n                                                name: \"$o\",\n                                            },\n                                            data_type: None,\n                                            ellipsis: None,\n                                            default: None,\n                                            modifiers: PromotedPropertyModifierGroup {\n                                                modifiers: [],\n                                            },\n                                        },\n                                    ],\n                                    commas: [],\n                                },\n                                right_parenthesis: Span {\n                                    line: 8,\n                                    column: 35,\n                                    position: 161,\n                                },\n                            },\n                            body: MethodBody {\n                                comments: CommentGroup {\n                                    comments: [],\n                                },\n                                left_brace: Span {\n                                    line: 9,\n                                    column: 5,\n                                    position: 167,\n                                },\n                                statements: [\n                                    Expression(\n                                        ExpressionStatement {\n                                            expression: AssignmentOperation(\n                                                Assign {\n                                                    left: PropertyFetch {\n                                                        target: Variable(\n                                                            SimpleVariable(\n                                                                SimpleVariable {\n                                                                    span: Span {\n                                                                        line: 10,\n                                                                        column: 7,\n                                                                        position: 175,\n                                                                    },\n                                                                    name: \"$this\",\n                                                                },\n                                                            ),\n                                                        ),\n                                                        arrow: Span {\n                                                            line: 10,\n                                                            column: 12,\n                                                            position: 180,\n                                                        },\n                                                        property: Identifier(\n                                                            SimpleIdentifier(\n                                                                SimpleIdentifier {\n                                                                    span: Span {\n                                                                        line: 10,\n                                                                        column: 14,\n                                                                        position: 182,\n                                                                    },\n                                                                    value: \"fake_variable\",\n                                                                },\n                                                            ),\n                                                        ),\n                                                    },\n                                                    equals: Span {\n                                                        line: 10,\n                                                        column: 28,\n                                                        position: 196,\n                                                    },\n                                                    right: Literal(\n                                                        String(\n                                                            LiteralString {\n                                                                value: \"'hellworld'\",\n                                                                span: Span {\n                                                                    line: 10,\n                                                                    column: 30,\n                                                                    position: 198,\n                                                                },\n                                                            },\n                                                        ),\n                                                    ),\n                                                },\n                                            ),\n                                            ending: Semicolon(\n                                                Span {\n                                                    line: 10,\n                                                    column: 41,\n                                                    position: 209,\n                                                },\n                                            ),\n                                        },\n                                    ),\n                                ],\n                                right_brace: Span {\n                                    line: 11,\n                                    column: 5,\n                                    position: 215,\n                                },\n                            },\n                        },\n                    ),\n                    ConcreteMethod(\n                        ConcreteMethod {\n                            comments: CommentGroup {\n                                comments: [],\n                            },\n                            attributes: [],\n                            modifiers: MethodModifierGroup {\n                                modifiers: [],\n                            },\n                            function: Span {\n                                line: 13,\n                                column: 5,\n                                position: 222,\n                            },\n                            ampersand: None,\n                            name: SimpleIdentifier {\n                                span: Span {\n                                    line: 13,\n                                    column: 14,\n                                    position: 231,\n                                },\n                                value: \"test\",\n                            },\n                            parameters: FunctionParameterList {\n                                comments: CommentGroup {\n                                    comments: [],\n                                },\n                                left_parenthesis: Span {\n                                    line: 13,\n                                    column: 18,\n                                    position: 235,\n                                },\n                                parameters: CommaSeparated {\n                                    inner: [\n                                        FunctionParameter {\n                                            comments: CommentGroup {\n                                                comments: [],\n                                            },\n                                            name: SimpleVariable {\n                                                span: Span {\n                                                    line: 13,\n                                                    column: 19,\n                                                    position: 236,\n                                                },\n                                                name: \"$a\",\n                                            },\n                                            attributes: [],\n                                            data_type: None,\n                                            ellipsis: None,\n                                            default: None,\n                                            ampersand: None,\n                                        },\n                                    ],\n                                    commas: [],\n                                },\n                                right_parenthesis: Span {\n                                    line: 13,\n                                    column: 21,\n                                    position: 238,\n                                },\n                            },\n                            return_type: None,\n                            body: MethodBody {\n                                comments: CommentGroup {\n                                    comments: [],\n                                },\n                                left_brace: Span {\n                                    line: 13,\n                                    column: 22,\n                                    position: 239,\n                                },\n                                statements: [\n                                    Return(\n                                        ReturnStatement {\n                                            return: Span {\n                                                line: 14,\n                                                column: 7,\n                                                position: 247,\n                                            },\n                                            value: Some(\n                                                Literal(\n                                                    Integer(\n                                                        LiteralInteger {\n                                                            value: \"1\",\n                                                            span: Span {\n                                                                line: 14,\n                                                                column: 14,\n                                                                position: 254,\n                                                            },\n                                                        },\n                                                    ),\n                                                ),\n                                            ),\n                                            ending: Semicolon(\n                                                Span {\n                                                    line: 14,\n                                                    column: 15,\n                                                    position: 255,\n                                                },\n                                            ),\n                                        },\n                                    ),\n                                ],\n                                right_brace: Span {\n                                    line: 15,\n                                    column: 5,\n                                    position: 261,\n                                },\n                            },\n                        },\n                    ),\n                ],\n                right_brace: Span {\n                    line: 17,\n                    column: 3,\n                    position: 266,\n                },\n            },\n        },\n    ),\n]\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>We will be finding the four common mistakes I defined before by navigating the tree. Let's start with finding the first mistake:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code> <span class=\"cp\">&lt;?php<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>According to the PSR-2 coding standard, the PHP opening tag should always be at the beginning of the file. When you don't <br>\ndo this, the white space will be sent to the client before executing your PHP code. Resulting in the <code>header already sent<\/code> error. This mistake will be easy to find in the AST. We can iterate through the items in the vector and use pattern matching to find the <code>FullOpeningTag<\/code> statement.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code>  <span class=\"k\">for<\/span> <span class=\"n\">statement<\/span> <span class=\"k\">in<\/span> <span class=\"n\">statements<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">match<\/span> <span class=\"n\">statement<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nn\">Statement<\/span><span class=\"p\">::<\/span><span class=\"nf\">FullOpeningTag<\/span><span class=\"p\">(<\/span><span class=\"n\">tag<\/span><span class=\"p\">)<\/span> <span class=\"k\">=&gt;<\/span>  <span class=\"n\">project<\/span><span class=\"nf\">.opening_tag<\/span><span class=\"p\">(<\/span><span class=\"n\">tag<\/span><span class=\"py\">.span<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span><span class=\"p\">),<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>As you can see in the AST, the information we need is stored in the struct <code>Span<\/code>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code> FullOpeningTag(\n        Span {\n            line: 1,\n            column: 1,\n            position: 0,\n        },\n    ),\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>We only need to check if the field line and column are higher than 0. If they are, it means the opening tag is not in the correct position, and we will <code>push<\/code> a suggestion into the field <code>suggestion<\/code> of the <code>file<\/code> parameter that is being passed to the <code>opening_tag<\/code> function.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code> <span class=\"k\">pub<\/span> <span class=\"k\">fn<\/span> <span class=\"nf\">opening_tag<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"k\">mut<\/span> <span class=\"k\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">span<\/span><span class=\"p\">:<\/span> <span class=\"n\">Span<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span><span class=\"p\">:<\/span> <span class=\"o\">&amp;<\/span><span class=\"k\">mut<\/span> <span class=\"n\">File<\/span><span class=\"p\">)<\/span> <span class=\"k\">-&gt;<\/span> <span class=\"o\">&amp;<\/span><span class=\"k\">mut<\/span> <span class=\"n\">Project<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">span<\/span><span class=\"py\">.line<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">1<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">file<\/span><span class=\"py\">.suggestions<\/span><span class=\"nf\">.push<\/span><span class=\"p\">(<\/span>\n                <span class=\"nn\">Suggestion<\/span><span class=\"p\">::<\/span><span class=\"nf\">from<\/span><span class=\"p\">(<\/span>\n                    <span class=\"s\">\"The opening tag &lt;?php is not on the right line. This should always be the first line in a PHP file.\"<\/span><span class=\"nf\">.to_string<\/span><span class=\"p\">(),<\/span>\n                    <span class=\"n\">span<\/span>\n                <span class=\"p\">))<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"k\">if<\/span> <span class=\"n\">span<\/span><span class=\"py\">.column<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">1<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">file<\/span><span class=\"py\">.suggestions<\/span><span class=\"nf\">.push<\/span><span class=\"p\">(<\/span><span class=\"nn\">Suggestion<\/span><span class=\"p\">::<\/span><span class=\"nf\">from<\/span><span class=\"p\">(<\/span>\n                <span class=\"nd\">format!<\/span><span class=\"p\">(<\/span>\n                    <span class=\"s\">\"The opening tag doesn't start at the right column: {}.\"<\/span><span class=\"p\">,<\/span>\n                    <span class=\"n\">t<\/span><span class=\"py\">.column<\/span>\n                <span class=\"p\">)<\/span>\n                <span class=\"nf\">.to_string<\/span><span class=\"p\">(),<\/span>\n                <span class=\"n\">span<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">));<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">self<\/span>\n    <span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p><em>I won't explain how to navigate to the correct statement in the AST for the rest of the mistakes.<\/em><\/p>\n\n<h3>\n  \n  \n  Class name that starts in lowercase.\n<\/h3>\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code><span class=\"kd\">class<\/span> <span class=\"nc\">uTesting<\/span> <span class=\"kd\">extends<\/span> <span class=\"nc\">FakeClass<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>When you do this, it's harder to distinguish a class between a variable and a method.<\/p>\n\n<p>I need to find out if the first letter of the name of the class is capitalized. The <code>String<\/code> type has a method <code>chars<\/code> that can convert the string into an iterator containing all the letters. You can grab the first character with the <code>next()<\/code> function. The <code>char<\/code> type has some valuable methods. The one we need is <code>is_uppercase()<\/code>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code><span class=\"k\">pub<\/span> <span class=\"k\">fn<\/span> <span class=\"nf\">has_capitalized_name<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"nb\">String<\/span><span class=\"p\">,<\/span> <span class=\"n\">span<\/span><span class=\"p\">:<\/span> <span class=\"n\">Span<\/span><span class=\"p\">)<\/span> <span class=\"k\">-&gt;<\/span> <span class=\"nb\">Option<\/span><span class=\"o\">&lt;<\/span><span class=\"n\">Suggestion<\/span><span class=\"o\">&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"o\">!<\/span><span class=\"n\">name<\/span><span class=\"nf\">.chars<\/span><span class=\"p\">()<\/span><span class=\"nf\">.next<\/span><span class=\"p\">()<\/span><span class=\"nf\">.unwrap<\/span><span class=\"p\">()<\/span><span class=\"nf\">.is_uppercase<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nf\">Some<\/span><span class=\"p\">(<\/span><span class=\"nn\">Suggestion<\/span><span class=\"p\">::<\/span><span class=\"nf\">from<\/span><span class=\"p\">(<\/span>\n                <span class=\"nd\">format!<\/span><span class=\"p\">(<\/span><span class=\"s\">\"The class name {} is not capitalized. The first letter of the name of the class should be in uppercase.\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">name<\/span><span class=\"p\">)<\/span><span class=\"nf\">.to_string<\/span><span class=\"p\">(),<\/span>\n                <span class=\"n\">span<\/span>\n            <span class=\"p\">));<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nb\">None<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Lowercase constants\n<\/h3>\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight php\"><code>    <span class=\"k\">const<\/span> <span class=\"no\">I_<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n    <span class=\"k\">const<\/span> <span class=\"no\">hello<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">null<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Similar to the capitalized class name, it's easier to distinguish a normal variable from a constant if the constant is in uppercase.<\/p>\n\n<p>I assume the constant is already upper cased, so I initialize the variable <code>is_uppercase = true<\/code>. When iterating through all of the letters, if I see a letter that is not in uppercase, I set the <code>is_uppercase = false<\/code>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code><span class=\"k\">pub<\/span> <span class=\"k\">fn<\/span> <span class=\"nf\">uppercased_constant_name<\/span><span class=\"p\">(<\/span><span class=\"n\">entry<\/span><span class=\"p\">:<\/span> <span class=\"n\">ConstantEntry<\/span><span class=\"p\">)<\/span> <span class=\"k\">-&gt;<\/span> <span class=\"nb\">bool<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">match<\/span> <span class=\"n\">entry<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">ConstantEntry<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">name<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">equals<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">value<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">let<\/span> <span class=\"k\">mut<\/span> <span class=\"n\">is_uppercase<\/span> <span class=\"o\">=<\/span> <span class=\"k\">true<\/span><span class=\"p\">;<\/span>\n            <span class=\"k\">for<\/span> <span class=\"n\">l<\/span> <span class=\"k\">in<\/span> <span class=\"n\">name<\/span><span class=\"py\">.value<\/span><span class=\"nf\">.to_string<\/span><span class=\"p\">()<\/span><span class=\"nf\">.chars<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n                <span class=\"k\">if<\/span> <span class=\"n\">l<\/span><span class=\"nf\">.is_uppercase<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"k\">false<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"n\">l<\/span><span class=\"nf\">.is_alphabetic<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n                    <span class=\"n\">is_uppercase<\/span> <span class=\"o\">=<\/span> <span class=\"n\">l<\/span><span class=\"nf\">.is_uppercase<\/span><span class=\"p\">()<\/span>\n                <span class=\"p\">}<\/span>\n            <span class=\"p\">}<\/span>\n\n            <span class=\"k\">return<\/span> <span class=\"n\">is_uppercase<\/span><span class=\"p\">;<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Defining parameters without a type.\n<\/h3>\n\n<p>I strongly advocate always defining the type for every parameter you declare. You need to define the type to avoid opening the gates to a bad interpretation of your code and introducing unnecessary bugs. In the AST, the <code>FunctionParameter<\/code> contains the parameter. We can pattern match the <code>data_type<\/code> field and the arm that has the <code>None<\/code> will need to return true. We will return the false for the <code>Some(_)<\/code> arm.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code><span class=\"k\">pub<\/span> <span class=\"k\">fn<\/span> <span class=\"nf\">function_parameter_without_type<\/span><span class=\"p\">(<\/span><span class=\"n\">parameter<\/span><span class=\"p\">:<\/span> <span class=\"n\">FunctionParameter<\/span><span class=\"p\">)<\/span> <span class=\"k\">-&gt;<\/span> <span class=\"nb\">bool<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">match<\/span> <span class=\"n\">parameter<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">FunctionParameter<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">comments<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">name<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">attributes<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">data_type<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">ellipsis<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">default<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">ampersand<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"k\">match<\/span> <span class=\"n\">data_type<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nb\">None<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"k\">return<\/span> <span class=\"k\">true<\/span><span class=\"p\">,<\/span>\n            <span class=\"nf\">Some<\/span><span class=\"p\">(<\/span><span class=\"n\">_<\/span><span class=\"p\">)<\/span> <span class=\"k\">=&gt;<\/span> <span class=\"k\">return<\/span> <span class=\"k\">false<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">},<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h1>\n  \n  \n  Conclusion\n<\/h1>\n\n<p>In part <a href=\"https:\/\/dev.to\/denzyldick\/how-i-made-it-impossible-to-write-spaghetti-code-dg4\">2<\/a>, I will show how to calculate the cyclomatic complexity of an example code. <\/p>\n\n<p>If you are a PHP developer, you know that a developer can make many more mistakes in PHP. In the future, this list will continue to grow into something more useful. <\/p>\n\n<p>Thanks for reading! <\/p>\n\n<p>Contribution is always welcome if you have a mistake you would like to add to <a href=\"https:\/\/github.com\/denzyldick\/phanalist\">phanalist<\/a>.  <\/p>\n\n","category":["php","codequality","codereview","rust"]}]}}