phpstan / phpstan-strict-rules Goto Github PK
View Code? Open in Web Editor NEWExtra strict and opinionated rules for PHPStan
License: MIT License
Extra strict and opinionated rules for PHPStan
License: MIT License
I don't think code should be allowed to call __construct
method.
E.g. $bob->__construct("Jane");
So https://phpstan.org/r/bce64dd4-7b61-4255-97e0-212d45563beb should report error that array<string, callable>
is returned instead of callable[]
.
Inspired by a discussing with @Ocramius, @alcaeus, and @Majkl578 today, some comparison operators should not allow an array
or string
types on its left side, or it will always result in false
. Examples:
<?php
var_dump('foo' > 4); //bool(false)
var_dump([1, 2, 3] < 2); //bool(false)
I'd like to discuss it before I propose an implementation for it.
Edit: Now PHPStan does detect comparisons between arrays and numbers: https://phpstan.org/r/eaa2bf97-ddb6-4118-a596-49333c7acf7a, which leave us just with the discussion of strings and numbers.
Require booleans in
if
,elseif
, ternary operator, after!
, and on both sides of&&
and||
.
I get what this rule is trying to accomplish, but imho truthiness is pretty intuitive and unsurprising for most types. For example, I don't see anything wrong with doing an if ($something)
where $something
is known to be Something|null
.
The obvious and afaik only exception would be strings, where e.g. "0"
is falsey... So I suggest to change this rule to:
Forbid strings in
if
,elseif
, ternary operator, after!
, and on both sides of&&
and||
.
Either by default or opt-in via a parameter.
https://phpstan.org/r/8f361ed5-7e15-4ffc-a6b0-3b5c33a3b419
PhpStorm complains about code like this, because an argument is being overwritten by a loop, which might not be intended behaviour.
I found it strange that overwriting from foreach
context is reported, but not from for
context.
Is there a reason for this not being reported, or just a missing feature?
I get a notice, say,
"RPC/Behavior/AttributeSerializerTrait.php (in context of class RPC\Controller\BaseController)"
Now regardless that it is explicitly states that it is "in context of" blah, phpstan complains that "return typehint of method" "has invalid type RPC\Behavior\BaseAttributes".
Which is of course missing, given that it is aliased/defined in BaseController.
Now I surely know that I could declare an abstract grandparent for the abstract parent attribute classes, so that I could put it fully qualified in the type hint of the method in the trait.
But it is not a question whether or not I should do this anyway (I did it at times, when I had any other use for this, and sometimes even when not; however, at other times, especially in the "Not Invented Here spirit", this is just infeasible.)
The question is that is it intentional that the trait's aliases are not resolved regardless of the context they are said to be evaluated in, or am I missing something?
After all, if this is indeed intentional, this seems to behave different from what PHP itself seems to do, which may be misleading.
in_array($needle, $haystack, false)
is a completely correct and explicit syntax when you do want to compare items by ==
.
With PHP 7.4 typed properties, following is possible:
class Foo
{
public Bar $bar;
}
$foo = new Foo();
var_dump($foo->bar);
Which produces an error.
Would it be useful to have a check that properties may be uninitialized only during __constructor
, and if the constructor does not set a value it is reported as an error?
See the following code. When evaluating $bar+1
in the second condition, we know that 0 === $foo
. (If not, the condition would have short-circuited.) Since 0 === $foo
, $bar
must be an integer. (If it was null
, the function would have returned in the first condition.) Hence evaluating $bar+1
should be fine. However, PHPStan gives the following error: Only numeric types are allowed in +, int|null given on the left side.
.
function foo(int $foo, ?int $bar): bool
{
if (0 === $foo && null === $bar) {
return true;
}
if (0 === $foo && 0 <= $bar+1) {
return true;
}
return false;
}
Similar to #30.
trait T
{
/**
* @param mixed $bar
* @param string $baz
*/
public function Foo($bar, string $baz): void
{
}
}
class C
{
use T;
}
parameters:
bootstrap: %rootDir%/../../../phpstan-bootstrap.php
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
"phpstan/phpstan": "^0.10.1",
"phpstan/phpstan-strict-rules": "^0.10.0",
Getting error:
------ ----------------------------------------------------------------------------
Line stan/T.php (in context of class common\stan\C)
------ ----------------------------------------------------------------------------
18 Method common\stan\C::Foo() has parameter $bar with no typehint specified.
------ ----------------------------------------------------------------------------
Hi, I would like to enable for Closures the two rules already present for normal functions, MissingFunctionParameterTypehintRule
and MissingFunctionReturnTypehintRule
.
I found that master branch has this commit 491540d which already enabled PHPStan\Rules\Missing\MissingClosureNativeReturnTypehintRule
, so I guess only the parameter typehint is still missing.
May I propose a PR for a MissingClosureParameterTypehintRule
?
Originally reported as slevomat/coding-standard#563 but impossible to implement there.
The idea is to ensure that final
classes don't contain any new protected
members. Such members can be made private
because there are no descendants that can use them. Special care has to be taken to avoid changing protected
methods from parent classes to private
, such as in this example:
abstract class MyAbstractClass
{
protected function protectedFunction()
{
echo 'foo';
}
}
final class MyClass extends MyAbstractClass
{
protected function protectedFunction()
{
echo 'bar';
}
}
In this case, protectedFunction
may not cause an error because its visibility can't be changed to private
.
When a child class overrides a method and renames one if its parameter, the @param
annotation of the parameter on the parent method is ignored. I think it should still be inherited.
In the following example:
class Foo
{
/**
* @param string $foo
*/
public function test($foo) { }
}
class Bar extends Foo
{
public function test($bar) { }
}
PHPStan will report the following error:
Method Bar::test() has parameter $bar with no typehint specified.
If I rename $bar
to $foo
, the error isn't reported anymore.
For the following code, PHPStan will issue an error: Return type (Traversable) of method Bar1::convert() should be covariant with return type (iterable<string>&Traversable) of method Foo::convert()
.
The most common way to inherit PHPDoc explicitly is to use {@inheritDoc}
(as in Bar2
), but using @inheritDoc
(as in Bar1
) is the correct way, according to the spec draft.
interface Foo
{
/**
* @return Traversable<string>
*/
public function convert(): Traversable;
}
abstract class Bar1 implements Foo
{
/**
* @inheritDoc
*/
abstract public function convert(): Traversable;
}
abstract class Bar2 implements Foo
{
/**
* {@inheritDoc}
*/
abstract public function convert(): Traversable;
}
abstract class Bar3 implements Foo
{
abstract public function convert(): Traversable;
}
Testing code:
interface FooInterface
{
/**
* @param mixed $value
*
* @return mixed
*/
public function test($value);
}
trait FooTrait
{
/**
* @param mixed $value
*
* @return mixed
*/
public function test($value)
{
}
}
class Bar implements FooInterface
{
use FooTrait;
}
Actual output:
------ -------------------------------------------------------------------------
Line Bar.php (in context of class App\Bar)
------ -------------------------------------------------------------------------
204 Method App\Bar::test() has no return typehint specified.
204 Method App\Bar::test() has parameter $value with no typehint specified.
------ -------------------------------------------------------------------------
[ERROR] Found 2 errors
Expected output: no error, both the parameter and the return type are correctly annotated.
I have this trait:
<?php
namespace App\Traits;
use DateTime;
use DateTimeInterface;
use Doctrine\ORM\Mapping as ORM;
trait EntityCreatedModified
{
/**
* @var DateTimeInterface|null
* @ORM\Column(type="datetime", nullable=true)
*/
private $created;
/**
* @var DateTimeInterface|null
* @ORM\Column(type="datetime", nullable=true)
*/
private $updated;
public function getCreated(): ?DateTimeInterface
{
return $this->created;
}
public function setCreated(?DateTimeInterface $created): self
{
$this->created = $created;
return $this;
}
public function getUpdated(): ?DateTimeInterface
{
return $this->updated;
}
public function setUpdated(?DateTimeInterface $updated): self
{
$this->updated = $updated;
return $this;
}
/**
* @ORM\PrePersist()
*/
public function onEntityCreated(): void
{
$this->setCreated(new DateTime());
$this->setUpdated(new DateTime());
}
/**
* @ORM\PreUpdate()
*/
public function onEntityUpdated(): void
{
if (!$this->created) {
$this->setCreated(new DateTime());
}
$this->setUpdated(new DateTime());
}
}
Then I have this abstract class:
<?php
namespace App\Entity;
use App\Traits\EntityCreatedModified;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\MappedSuperclass()
*/
abstract class AbstractBaseEntity
{
use EntityCreatedModified;
}
I get this error:
------ --------------------------------------------------------------------------------------
Line Traits/EntityCreatedModified.php (in context of class App\Entity\AbstractBaseEntity)
------ --------------------------------------------------------------------------------------
15 Property App\Entity\AbstractBaseEntity::$created has no typehint
specified.
21 Property App\Entity\AbstractBaseEntity::$updated has no typehint
specified.
------ --------------------------------------------------------------------------------------
When I extend the abstract class or use the trait directly in a concrete class, there is no error.
The check checkAlwaysTrueCheckTypeFunctionCall
incorrectly assumes that the result of adding two integers is always an integer:
function addExact(int $augend, int $addend) : int
{
$result = $augend + $addend;
// Call to function is_int() with int will always evaluate to true.
if (!\is_int($result)) {
throw new OverflowException('The result overflows the range of an integer.');
}
return $result;
}
addExact(\PHP_INT_MAX, 1);
Function "explode" return a array or false value. https://secure.php.net/manual/en/function.explode.php
$a = explode($separator, $array); if (\is_array($a)) { ... }
error message: "Call to function is_array() with array<int, string> will always evaluate to true."
Phpstan Version: 0.11.1
So far we have had disabled missing typehints rule:
- "~^(Method|Property) .+::.+(\\(\\))? (has parameter \\$\\w+ with no|has no return|has no) typehint specified$~"
Because it reported errors also for classes where we disabled the same reporting with @phpssSuppress
used for CodeSniffer. And that was disabled for a reason.
For example, we have overriden PHPUnit method
/**
* Returns a test double for the specified class.
*
* @param string|string[] $originalClassName
*
* @throws Exception
* @throws \InvalidArgumentException
*/
protected function createMock($originalClassName): MockObject
{
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->getMock();
}
with
/**
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
*/
protected function createMock($originalClassName) : MockObject
{
throw new \BadMethodCallException('Use Mockery instead.');
}
We suppresed type hint checks because we have to follow parent signature from external library so types cannot be added.
However, this PHPStan strict check is very handy but also it's very exhausting to manually enumarete all places to ignoreErrors in config.
As example I have modified the MissingMethodParameterTypehintRule
rule in a following way
private function checkMethodParameter(MethodReflection $methodReflection, ParameterReflection $parameterReflection, ?Doc $doc): ?string
{
$parameterType = $parameterReflection->getType();
if (
$parameterType instanceof MixedType &&
!$parameterType->isExplicitMixed() &&
(
$doc === null ||
preg_match(
'~(@phpcsSuppress SlevomatCodingStandard\.TypeHints\.TypeHintDeclaration\.MissingParameterTypeHint|@inheritdoc)~',
$doc->getText()
) === 0
)
) {
return sprintf(
'Method %s::%s() has parameter $%s with no typehint specified.',
$methodReflection->getDeclaringClass()->getDisplayName(),
$methodReflection->getName(),
$parameterReflection->getName()
);
}
return null;
}
But I don't see how it would fit in the existing codebase when PR is sent. So I came to ask for ideas/share this snippet for anyone who would like to use it. Feel free to close this, I don't see a way how this could be integrated here in a clean way myself. IMO combining with PHPCS rules is exceeding the responsibility of this library.
Similar to arithmetic operators (+
/-
/*
//
/**
/%
), loose comparison operators should only be used for numeric values. This is true for ==
, !=
, <
, >
, <=
, >=
and <=>
.
Using any of these operators for non-numeric values may lead to unexpected results.
The option to disallow ==
and !=
completely doesn't cover the full problem as other comparison operators are still allowed and might give unexpected result. It also disallows cases where you do want to use ==
because you're comparing numbers.
42 == 42.0 // true
42 == "42" // true
42 == "4.2e1" // true
42 < "0xf1" // true
// convert to int, I guess
1000 >= "42 bytes" // true
(int)"42 bytes" // 42
// but not always :-(
(int)"4.2e1 bytes" // 42
1000 >= "4.2e1 bytes" // false ??
Universal rules of logic state that if a > b
and b > c
than a > c
$a = '42';
$b = 10;
$c = '9 dwarfs';
$a > $b // true
$b > $c // true
$a > $c // false ??
The spaceship operator should also not be used for strings.
function cmp1(string $x, string $y) {
return $x <=> $y;
}
function cmp2(string $x, string $y) {
return ($x . 'Foo') <=> ($y . 'Foo');
}
// Both functions should do the same, but...
cmp1("55", "5.5e1"); // 0
cmp2("55", "5.5e1"); // 1
The logic behind wether or not a string is converted to a number is just to complex. It's party explained in the manual, but that's not conclusive.
For strings you SHOULD always use ===
or strcmp
.
While ==
could be useful to compare objects, the strange behaviour on strings makes this too dangerous.
$one = (object)['a' => 0];
$two = (object)['a' => '0.0'];
$three = (object)['a' => 'bar'];
$one == $two; // true
$one == $three; // true
$two == $three; // false
Continuing work from phpstan/phpstan#690... /cc @iluuu1994
new
ing deprecated class@method
and @property
annotationsSome of them are a little bit more obscure so I don't require all of them to exist right away, this is just a list of what I could think of.
https://phpstan.org/r/33f4a31d-1316-463d-b7aa-6978623175de
Expected result: no error
PHPStan don't report code like this (boolean used as array)
$x = FALSE;
var_dump($x['asdf']);
https://phpstan.org/r/d76cc038-f93d-4766-a256-2770437d9fee
Error because code uses boolean variable like an array.
PHP's negative operator can return true
for a number of values: https://3v4l.org/OPBti.
Instead of using it, an explicit condition ($foo
=== false, for example) should be used instead.
The rule itself should be easy to create, but I'd like to discuss it first :)
What is wrong with shortcut $doSomething && $something()
?
Full snippet:
<?php
declare(strict_types = 1);
namespace Foo;
class Configurator
{
public function loadConfig()
{
return $this;
}
}
$configurator = new Configurator();
$devMode = true;
$devMode && $configurator->loadConfig();
Error:
------ -----------------------------------------------------------------------
Line bootstrap.php
------ -----------------------------------------------------------------------
18 Only booleans are allowed in &&, Foo\Configurator given on
the right side.
------ -----------------------------------------------------------------------
Hi,
I might have found a bug when using the instanceof
with Doctrine collections and entities.
Code example:
use Doctrine\Common\Collections\ArrayCollection;
use App\Entity\TextEntity;
/**
* @param TextEntityList|TextEntity[]|ArrayCollection $text
*/
public function setText($text): void
{
if ($text instanceof TextEntityList) { // just a regular object
$this->text = new ArrayCollection($text->getArrayValues());
} elseif ($text instanceof ArrayCollection) {
$this->text = $text;
} else { // this should happen only when $text is an array of TextEntity (which is a standard Doctrine entity object)
$this->text = new ArrayCollection($text);
}
}
PHPStan Strict Rules evaluates this code with the following error:
Instanceof between Doctrine\\Common\\Collections\\ArrayCollection&iterable<App\Entity\TextEntity> and Doctrine\\Common\\Collections\\ArrayCollection will always evaluate to true
In reality, PHP does not evaluate this condition as always true and the else
branch is, in fact, reachable.
Is there any solution I am missing or is it a bug?
Thank you.
Hi,
I'm opening issue here since this is the strict ruleset and I want to suggest to disallow usage of backtick operator.
Basically disallow to do something like this
<?php
$ls = `ls -la`;
echo "<pre>$ls</pre>";
Currently there is a RFC to deprecate them and internals are currently having a debate regarding the RFC.
The point is that you can replace backtick operators with shell_exec()
which much more explicit.
Exampe:
<?php declare(strict_types=1);
$arr = [];
if ($arr) {
echo 'some';
}
if (!empty($arr)) {
echo 'some';
}
If I have some array in return and check it in "if condition" I got next errors:
5 Only booleans are allowed in an if condition, array given.
9 Construct empty() is not allowed. Use more strict comparison.
So my question is: How it should be fixed?
Hello,
I have several magic methods in my code that I am unable to typehint correctly with phpstan-strict-rules.
Example:
public function __get(string $name) : mixed
{
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Undefined property via __get(): ' . $name .
' in ' . $trace[0]['file'] .
' on line ' . $trace[0]['line'],
E_USER_NOTICE
);
return null;
}
The method can return arrays, boolean, strings or null, which I thought was called mixed. When I add mixed as typecast though I get two errors:
58 Return typehint of method Boka10\Skeleton::__get() has invalid type
Boka10\Traits\mixed.
72 Method Boka10\Skeleton::__get() should return Boka10\Traits\mixed but
returns null.
(Boka10\Traits is the namespace that the trait defining __get is in)
What would be the correct way to say "well, this method can return anything at this point"?
Using phpstan dev-master@c6a8cd1 with PHP 7.2.10 and declare(strict_types=1);
is set
Hi. Would there be interest in a new rule that checks that static methods are called with ::
and not with ->
? I see that fairly regulary in the wild (mainly with PHPUnit
's asserts) and it's driving me crazy.
Steps to reproduce:
@var
annotation.@var
annotationHello,
Strict-rules require all class properties to have typehint, although the ones that are specified in the constructor are perfectly inferred by the IDE.
Maybe we could make the property typehint optional if type of the property is specified in the constructor?
The code:
<?php declare(strict_types = 1);
class Foo
{
private $bar;
public function __construct(Bar $bar)
{
$this->bar = $bar;
}
}
class Bar {}
Output:
+------------------------------------------------------+
| Line | test.php |
+------------------------------------------------------+
| 5 | Property Foo::$bar has no typehint specified. |
+------------------------------------------------------+
[ERROR] Found 1 error
Expected output:
No errors
Hi,
as for buildin functions, we can require types for parameters/return type for callables and closures.
Any interest here?
I'm not sure if this is an issue with PHPStan or the strict rules, but it kicks in only when using strict rules.
As far as I understand, {@inheritdoc}
should not be required to inherit the types from the parent.
<?php
interface Foo
{
/**
* @param int|string $foo
*
* @return mixed
*/
public function foo($foo);
}
class Bar implements Foo
{
public function foo($foo)
{
return null;
}
}
This results in:
------ -----------------------------------------------------------------
Line src/Bar.php
------ -----------------------------------------------------------------
5 Method Bar::foo() has no return typehint specified
5 Method Bar::foo() has parameter $foo with no typehint specified
------ -----------------------------------------------------------------
Once I add {@inheritdoc}
to Bar::foo
it works as expected.
I have created a custom rule that disallows use of \DateTimeInterface::ISO8601
and \DATE_ISO8601
constants because they are not actually ISO 8601 compatible (ATOM is). It's a common pitfall and I wanted to prevent it from happening again in my team.
I could cook up a PR for this repository in a matter of minutes. Would that be appreciated or does the rule not really fit in with this repository's idealogy?
https://www.php.net/manual/en/class.datetimeinterface.php#datetime.constants.iso8601
With the following code:
// T.php
trait T
{
/** @var int */
private $foo;
}
// C.php
class C
{
use T;
}
And the MissingPropertyTypehintRule added like this:
services:
-
class: PHPStan\Rules\Properties\MissingPropertyTypehintRule
tags:
- phpstan.rules.rule
When running phpstan with T.php and C.php as input, I get the following error:
------ -----------------------------------------------------
Line T.php (in context of class C)
------ -----------------------------------------------------
12 Property C::$foo has no typehint specified.
------ -----------------------------------------------------
Properties type hints are not recognized in anonymous classes declared under namespaces:
https://phpstan.org/r/1b8cda36-c6e9-4386-affd-294dd3034f89
The rule would prevent declaring dynamic properties unless the class implements __set
.
The idea originated from discussions around this topic in the internals:
https://externals.io/message/104620
I'm not sure if this is an issue with PHPStan or strict rules, but it kicks in only when using strict rules.
trait Foo
{
/**
* @var string
*/
protected $foo;
}
trait Bar
{
use Foo;
}
class Baz
{
use Bar;
}
results in:
------ ----------------------------------------------
Line src/Foo.php (in context of class Baz)
------ ----------------------------------------------
8 Property Baz::$foo has no typehint specified
------ ----------------------------------------------
Const overrides violate const invariants and are not LSP-compliant (types can be changed randomly).
There may be dragons when constants are used with static::
(sniff request to forbid that: slevomat/coding-standard#473) or $object::
.
Any occurence of a constant override should be (abstract) method instead.
Edge case: constants like NAME
on each member of a tree?
Hi,
I would like to report methods which return type is not known - no php typehint/phpdoc.
I know that there is rule that checks whether function returns which it typehints - eg.
function a(): string
{
return new stdClass;
}
this is correctly reported as should return string but returns stdClass
.
But when no typehint is defined I would expected that function "returns" void
.
https://phpstan.org/r/10e7cc35381dcada1f8b1f54095fb0b1
should return void but returns stdClass
When using PHPUnit, assertions and some other methods are normally called dynamically (e.g. $this->assertSame()
or $this->once()
), although they are declared as static methods. This of course triggers the DynamicCallOnStaticMethodsRule
for all these calls.
According to the author of PHPUnit, it is encouraged to use $this->
instead of self::
.
Keeping that in mind the question is: Should the PHPUnit classes (e.g. PHPUnit\Framework\Assert
and PHPUnit\Framework\TestCase
) be excluded from the DynamicCallOnStaticMethodsRule
? (Maybe through a parameter to enable/disable this?)
Running the following code with phpstan-strict-rules results in an unexpected error 9 Strict comparison using !== between false and string will always evaluate to true.
After a short analysis it seems like readdir
has been typehinted (in functionMap.php
) with string
only instead of string|false
(see http://php.net/manual/de/function.readdir.php). Is this a bug in the php docs, phpstan or am i missing something here?
<?php declare(strict_types = 1);
function getFiles(string $dir)
{
$files = [];
$handle = opendir($dir);
if (false !== $handle) {
while (false !== ($file = readdir($handle))) {
if ('.' !== $file && '..' !== $file) {
$files[] = $file;
}
}
closedir($handle);
}
return $files;
}
Running
"phpstan/phpstan": "^0.10.1",
"phpstan/phpstan-strict-rules": "^0.10.0",
Hi there,
My issue is that for
class A
{
private string $b;
}
I get the following error:
Property A::$b has no typehint specified.
PHPStan should recognize the native type of the property instead of only using the PHPDoc type.
There are some cases where using empty improves code readability and at no risk.
Consider the following example:
class Foo {
// Always an array
private $values = [];
public function isEmpty() : bool
{
// This is a way better than \count($this->values) in terms of readability
return empty($this->values);
}
}
In that sense, I'd like to propose to now warn about the use of empty
in cases where the subject can only be an array.
Can such a check be made? I would like to force all files in a project to implement
<?php
declare(strict_types=1);
...
I tried looking but the closest I found were style guide rules for other tools.
Related: phpstan/phpstan#791
A weak comparison error should be thrown for such case:
<?php declare(strict_type=1);
function getCount(): ?int
{
return 0 === rand(1, 5) % 5 ? 42 : null;
}
if (!getCount()) {
echo 'test';
}
Because 0
and null
will go to the same result.
But this case must not rise an error:
<?php declare(strict_type=1);
function getUpdatedAt(): ?\DateTime
{
return 0 === rand(1, 5) % 5 ? new \DateTime('now') : null;
}
if (!getUpdatedAt()) {
echo 'test';
}
Because it's currently fine, no confusable value can be return here.
Not sure if rules that analyse composer.lock are within the scope of this project, but I'd find it useful (from a housekeeping stand point) to be able to configure phpstan to check that any package that has phpstan/phpstan listed in it's dependencies, then report those that don't also require phpstan/phpstan-strict-rules
i.e.
require-dev
Specifying a type hint for a resource parameter prevents it of being validated, as demonstrated in
https://phpstan.org/r/3353e83f-f844-4f24-a68f-f3e2ebb704eb
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.