NoColor — validate the architecture of your PHP project

Overview

image

Go Report Card GitHub license

NoColor — validate the architecture of your PHP project

NoColor is an architecture validation tool based on the concept of colored functions. This concept was originally invented for KPHP and later exposed as a separate tool to be used in regular PHP projects.

NoColor and Deptrac have similar goals: they both search for bad architectural patterns. But NoColor uses an absolutely different scenario: function coloring. Unlike Deptrac, NoColor analyzes call chains of any depth and supports type inferring. Continue reading NoColor vs Deptrac.

NoColor performs static code analysis, it has no runtime overhead. It supports type inferring to handle instance method calls, but dynamic invocations like A::$method() can't be statically analyzed.

NoColor is built on top of NoVerify and written in Go.

Optionally, install an experimental plugin for PhpStorm that brings some handy features.

Theoretically, the same concept can be implemented for almost every language. NoColor targets PHP.

A brief intro to colors

Using the @color PHPDoc tag, you assign colors to a function. When a function calls another one, their colors combine to a chain:

/** @color green */
function f1() { f2(); }

// this function has no color (it's transparent)
function f2() { f3(); }

/** @color red */
function f3() { /* ... */ }

f1 f2 f3 colored

In the palette, you define rules of colors mixing, as this error rule:

green red: calling red from green is prohibited

All possible call chains are pattern-matched against rules. Hence, f1 -> f2 -> f3 will trigger the error above.

A color is anything you want: @color api, or @color model, or @color controller. With the palette, you define arbitrary patterns and exceptions. You can mark classes and use namespaces. You can express modularity and even simulate the internal keyword.

Continue reading about colors here

Getting started

The Getting started page contains a step-by-step guide and copy-paste examples.

The palette.yaml file

Once you call

nocolor init

at the root of your project, it creates an example palette.yaml file. It contains rules of color mixtures:

first group title:
- rule1 color pattern: rule1 error or nothing
- rule2 color pattern: rule2 error or nothing
# other rules in this group

# optionally, there may be many groups

Consider the Configuration page section.

Running NoColor

At first, install NoColor to your system. The easiest way is just to download a ready binary.

Then, execute this command once at the root of your project:

nocolor init

It will create a palette.yaml file with some examples.

Every time you need to check a project, run

nocolor check

to perform checking in the current directory, or

nocolor check ./src

to perform checks in another folder (or many).

To exclude some paths from analyzing, or to include the ./vendor dir, consider all possible command-line options.

Limitations and speed

As for now, NoColor supports PHP 7.4 language level. It depends on a Go package php-parser which is currently frozen. This restriction can be overcome in the future.

NoColor scales easily to the capacities provided. Depending on the number of cores and the speed of a hard disk, NoColor can process up to 300k lines per second.

The number of groups, colors, and selectors is unlimited, though the more functions are colored — the slower NoColor would work, as the number of colored graph paths exponentially increases. Typically, 99% of classes/functions are supposed to be left transparent.

All available call chains are calculated on a static analysis phase, there is no runtime overhead. NoColor uses some tricky internal optimizations to avoid useless depth searching in a call graph. Every possible colored call chain is matched against all rules in the palette.

Remember, that PHP is an interpreted language and allows constructions that can't be statically analyzed. If you write something like SomeClass::$any_function() or new $class_name, NoColor can't do anything about it.

Contributing

Feel free to contribute to this project. See CONTRIBUTING.md for more information.

The License

NoColor is distributed under the MIT License, on behalf of VK.com (V Kontakte LLC).

Comments
  • Flexible symbol discovery

    Flexible symbol discovery

    Is your feature request related to a problem? Please describe.

    Deptrac matches names by regexps, NoColor needs PHPDoc tags

    Describe the solution you'd like

    image

    Describe alternatives you've considered N/A

    Additional context Again, mostly a loose thought, but having the option to mark classes by regex and annotations would be nice. Using one over the other shouldn't really interfere, it's just the discovery process that needs to be decoupled. Again: open for discussion/collaboration on this if it's a feature that'd be appreciated.

    enhancement 
    opened by nmokkenstorm 5
  • @color of method isn't merged to @color of the class

    @color of method isn't merged to @color of the class

    Describe the bug I have a class with @color and its method with another @color. I expect the method to have both colors (in order class-color + method-color), but it works somehow differently.

    To Reproduce PHP code

    /** @color controller */
    class Controller {
      /** @color allow-model-call */
      static function act() {
        Model::act();
      }
    }
    
    /** @color model */
    class Model {
      static function act() {}
    }
    

    palette.yaml

    demo:
    - controller model: restricted dependency
    - controller allow-model-call model: ""
    

    Expected behavior No error (the second rule should be matched);

    Actual behavior An error (the first rule is matched) BTW, if I add @color allow-model-call as a second color to the Controller class itself, everything works as expected. So, the problem is only in class+method case.

    bug 
    opened by unserialize 1
  • Invoking a constructor doesn't match an error rule

    Invoking a constructor doesn't match an error rule

    Describe the bug When I write $m = new Model, this is not seen as a dependency regardless of the @color tag above the Model class.

    To Reproduce PHP code:

    /** @color controller */
    class Controller {
      static function act() {
        $m = new Model;
      }
    }
    
    /** @color model */
    class Model {
      function act() {}
    }
    

    palette.yaml:

    demo:
    - controller model: restricted dependency
    

    Expected behavior An error.

    Actual behavior No error.

    BTW, if I insert a call $m->act() after the constructor call, this error is shown

    bug 
    opened by unserialize 1
  • cmd: added initial support of PHP 8

    cmd: added initial support of PHP 8

    Type: feature

    At the moment we are correctly parsing all PHP 8 and 8.1 except intersection types.

    A nullsafe method call is treated like a normal method call and creates a link.

    PHP 8 is now by default. In order to parse the project as PHP 7, added the --php7 flag.

    enhancement 
    opened by i582 0
  • cmd: improved `cache-clear` command

    cmd: improved `cache-clear` command

    Type: refactoring

    Added a message about the successful deletion of the cache, and now, in case of a strange path, a message is displayed without panic.

    refactoring 
    opened by i582 0
  • internal/palette: fixed a bug due to which the wrong colors could be set for functions on subsequent launches

    internal/palette: fixed a bug due to which the wrong colors could be set for functions on subsequent launches

    Type: bugfix

    Since the map in Golang does not have a certain order within it, the first group could become the second and because of this, the color numbers could start to match the colors from another group, which led to errors.

    bug 
    opened by i582 0
  • internal/walkers: added support for the case when a variable with a class type is passed to the new operator

    internal/walkers: added support for the case when a variable with a class type is passed to the new operator

    Type: feature

    Added support for the case when a variable with a class type is passed to the new operator In this case, we expect that the constructor of this class is called.

    enhancement 
    opened by i582 0
  • internal: fixed collectors of colors

    internal: fixed collectors of colors

    Type: bugfix

    • Added full tracking of class colors, now all classes will be cached;

    • RootIndexer now sets colors for classes and functions and also handles cases when a class and method have colors that should be mixed;

    • RootChecker no longer sets colors for classes and functions, but only checks them, which can now issue several warnings at once, rather than one.

    Fixes #3

    bug 
    opened by i582 0
  • internal/callgraph,palette,pipes: improved performance for callstack.Append and .PopBack

    internal/callgraph,palette,pipes: improved performance for callstack.Append and .PopBack

    Type: refactoring

    Improved implementations for functions for adding and removing functions from the call stack, as well as in the function eachComponent the nextColoredUniq map is now created with 10 places.

    The change increases performance by 2-3%.

    enhancement 
    opened by i582 0
  • allow analysis of magic calls

    allow analysis of magic calls

    Is your feature request related to a problem? Please describe.

    Remember, that PHP is an interpreted language and allows constructions that can't be statically analyzed. If you write something like SomeClass::$any_function() or new $class_name, NoColor can't do anything about it.

    Describe the solution you'd like

    The amazing PHPStan by Ondřej Mirtes solves this using an extension structure to dynamically verify 'magic' calls

    Describe alternatives you've considered

    N/A

    Additional context

    This issue is more of an FYI than anything else, but I'd be willing to look into making this work if that's something that'd be appreciated.

    enhancement 
    opened by nmokkenstorm 5
Releases(v1.1.0)
Owner
VK.com
VK.com
Template project to get started with a simple API skeleton in Go and Docker

A template project to create a Docker image for a Go application. The example application exposes an HTTP endpoint through a REST API packaged as a static binary.

Harsh Mishra 11 Apr 4, 2022
ide-gen is a tool for development workspace prepare automation by automatic VCS repositories discovery and clone and project generation for supported IDEs.

ide-gen is a tool for development workspace prepare automation by automatic VCS repositories discovery and clone and project generation for supported IDEs.

null 8 May 8, 2022
🔥 Continuous profiling platform — debug performance issues in your code!

Pyroscope is an open source continuous profiling platform.

Pyroscope 6.7k Nov 26, 2022
Aegis is a library that allows you detect if your software is being debugged or not on Linux, FreeBSD, NetBSD, OpenBSD and Windows

Aegis is a library that allows you detect if your software is being debugged or not on Linux, FreeBSD, NetBSD, OpenBSD and Windows. You can use it natively from C or use the Go bind.

Rafael Santiago 28 Aug 29, 2022
go-pry - an interactive REPL for Go that allows you to drop into your code at any point.

go-pry go-pry - an interactive REPL for Go that allows you to drop into your code at any point. Example Usage Install go-pry go get github.com/d4l3k/g

Tristan Rice 2.9k Nov 26, 2022
PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. You can use PHP like functions in your app, module etc. when you add this module to your project.

PHP Functions for Golang - phpfuncs PHP functions implementation to Golang. This package is for the Go beginners who have developed PHP code before. Y

Serkan Algur 52 Aug 26, 2022
Traefik config validator: a CLI tool to (syntactically) validate your Traefik configuration filesTraefik config validator: a CLI tool to (syntactically) validate your Traefik configuration files

Traefik Config Validator Note This is currently pre-release software. traefik-config-validator is a CLI tool to (syntactically) validate your Traefik

Thomas Klinger 0 Dec 16, 2021
Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package.

Goridge is high performance PHP-to-Golang codec library which works over native PHP sockets and Golang net/rpc package. The library allows you to call Go service methods from PHP with a minimal footprint, structures and []byte support.

Spiral Scout 1.1k Nov 23, 2022
go-for-php php-to-go

easy-func 项目介绍 使用 golang 来翻译 php 函数。可以看做php函数在golang的映射字典。

null 13 Nov 12, 2022
Go (Golang) Clean Architecture based on Reading Uncle Bob's Clean Architecture

go-clean-arch Changelog v1: checkout to the v1 branch Proposed on 2017, archived to v1 branch on 2018 Desc: Initial proposal by me. The story can be r

Iman Tumorang 6.9k Nov 30, 2022
Golang Clean Architecture based on Uncle Bob's Clean Architecture and Summer internship in 2021

clean-architecture-api Description This is an example of implemention of Clean Architecture in Golang projects. This project has 4 layer : Infrastruct

daiki sakuma 4 Feb 20, 2022
Hexagonal architecture paradigms, such as dividing adapters into primary (driver) and secondary (driven)Hexagonal architecture paradigms, such as dividing adapters into primary (driver) and secondary (driven)

authorizer Architecture In this project, I tried to apply hexagonal architecture paradigms, such as dividing adapters into primary (driver) and second

Renato Benatti 0 Dec 7, 2021
This is a POC (Proof of Concept) using Hexagonal Architecture, SOLID, DDD, Clean Code, Clean Architecture

Projeto Planetas Star Wars: Esse projeto de trata de uma POC utilizando os conceitos de Clean Arch, Hexagonal Arch, Clean Code, DDD, e SOLID. O princi

Marcelo Martins 0 Feb 10, 2022
This project is a Library to validate a pull secret

lib-ps-validator Description This repository and its contents are completely UNSUPPORTED in any way and are not part of official documentation. Lib to

Red Hat Systems Engineering Team 3 Jul 21, 2021
A demo project shows how to use validator to validate parameters

validator-demo This project is a demo project shows how to use validator to validate parameters use case install requirements go get github.com/favadi

ziyi.wang 1 Jan 10, 2022
Qfy - Self-hosted implementation of Synthetics - Monitoring checks to validate your service availability

qfy Self-hosted implementation of Synthetics - Monitoring checks to validate you

Milan Pavlik 1 Feb 23, 2022
Serpscan is a powerfull php script designed to allow you to leverage the power of dorking straight from the comfort of your command line.

SerpScan Serpscan is a powerful PHP tool designed to allow you to leverage the power of dorking straight from the comfort of your command line. Table

Alaa Abdulridha 47 Nov 11, 2022
Library providing routines to merge and validate JSON, YAML and/or TOML files

CONFLATE Library providing routines to merge and validate JSON, YAML, TOML files and/or structs (godoc) Typical use case: Make your application config

Andy 26 Sep 26, 2022
Govalid is a data validation library that can validate most data types supported by golang

Govalid is a data validation library that can validate most data types supported by golang. Custom validators can be used where the supplied ones are not enough.

null 61 Apr 22, 2022