Phan은 거짓 긍정을 최소화하는 것을 선호하는 PHP용 정적 분석기입니다. Phan은 정확성보다는 부정확성을 증명하려고 시도합니다.
Phan은 일반적인 문제를 찾고 유형 정보를 사용할 수 있거나 추론할 수 있는 경우 다양한 작업에 대한 유형 호환성을 확인합니다. Phan은 흐름 제어에 대해 (포괄적이지는 않지만) 잘 이해하고 있으며 몇 가지 사용 사례(예: 배열, 정수 및 문자열)에서 값을 추적할 수 있습니다.
Phan을 사용하는 가장 쉬운 방법은 Composer를 이용하는 것입니다.
composer require phan/phan
Phan이 설치되면 프로젝트에 .phan/config.php
파일을 생성하여 Phan에게 소스 코드 분석 방법을 알려줄 수 있습니다. 일단 구성되면 ./vendor/bin/phan
을 통해 실행할 수 있습니다.
Phan 5는 php-ast 확장(1.1.1+ 권장)이 포함된 PHP 7.2+에 의존하며 PHP 버전 7.0-8.2 구문 분석을 지원합니다. php-ast 설치 지침은 여기에서 확인할 수 있습니다. (Phan은 CLI 옵션 --allow-polyfill-parser
사용하여 php-ast 없이 사용할 수 있지만 문서 주석 구문 분석에는 약간의 차이가 있습니다)
Wiki에는 Phan 사용에 대한 자세한 정보가 있습니다.
Phan은 다음과 같은 종류의 분석을 수행할 수 있습니다.
object
, void
, iterable
, ?T
, [$x] = ...;
, 음수 문자열 오프셋, 다중 예외 catch 등).--dead-code-detection
전달)--unused-variable-detection
전달)--redundant-condition-detection
전달)use
내역을 확인하세요. --automatic-fix
사용하면 이러한 문제 유형과 기타 몇 가지 문제 유형을 자동으로 수정할 수 있습니다.@template
)을 지원합니다.int[]
, UserObject[]
, array<int,UserObject>
등과 같은 일반 배열을 지원합니다.array{key:string,otherKey:?stdClass}
등과 같은 배열 모양을 지원합니다. (내부 및 PHPDoc 태그에서) 이는 array{requiredKey:string,optionalKey?:string}
통해 배열 모양의 필드가 선택 사항임을 나타내는 것도 지원합니다. ( @param
에 유용함)@deprecated
주석을 지원합니다.@internal
주석을 지원합니다.@suppress <ISSUE_TYPE>
주석을 지원합니다.@property <union_type> <variable_name>
)@method <union_type> <method_name>(<union_type> <param1_name>)
)class_alias
주석 지원(실험적, 기본적으로 꺼짐)@phan-closure-scope
(예)를 통해 클로저가 바인딩될 클래스 표시를 지원합니다.array_map
, array_filter
및 기타 내부 배열 함수에 전달된 클로저 및 반환 유형 분석을 지원합니다.pcntl
필요)Phan에서 감지할 수 있는 모든 문제에 대한 설명과 예는 Phan 문제 유형을 참조하세요. 각 오류 유형의 정의를 보려면 PhanIssue를 살펴보세요.
지속적인 분석을 수행하는 프로세스가 어떤 모습일지 알아보려면 대규모 엉성한 코드 베이스 분석을 위한 튜토리얼을 살펴보세요.
Phan은 언어 서버 프로토콜을 통해 오류 검사, "정의로 이동" 지원 등을 위해 다양한 편집기 및 IDE에서 사용할 수 있습니다. 편집자와 도구는 더 간단한 데몬 모드를 사용하여 프로젝트의 개별 파일에 대한 분석을 요청할 수도 있습니다.
다양한 검사에 대한 몇 가지 예를 보려면 테스트 디렉토리를 참조하세요.
Phan은 불완전하므로 PHP 기반 로켓 유도 시스템에 결함이 없음을 증명하는 데 사용해서는 안 됩니다.
플러그인을 통해 추가 분석 기능이 제공되었습니다.
{ throw new Exception("Message"); return $value; }
)*printf()
형식 문자열 확인(및 일반적인 오류 확인)preg_*()
에 전달된 PCRE 정규 표현식이 유효한지 확인@suppress
주석을 확인합니다.예: Phan의 자기 분석용 플러그인.
Phan을 설치한 후 분석할 코드를 찾을 수 있는 위치와 분석 방법에 대한 세부 정보로 Phan을 구성해야 합니다. Phan에게 소스 코드를 찾을 수 있는 위치를 알려주는 가장 쉬운 방법은 .phan/config.php
파일을 만드는 것입니다. 간단한 .phan/config.php
파일은 다음과 같습니다.
<?php
/ * *
* This configuration will be read and overlaid on top of the
* default configuration . Command line arguments will be applied
* after this file is read .
* /
return [
// Supported values : `'5.6'` , `'7.0'` , `'7.1'` , `'7.2'` , `'7.3'` , `'7.4'` ,
// `'8.0'` , `'8.1'` , `'8.2'` , `'8.3'` , `null` .
// If this is set to `null` ,
// then Phan assumes the PHP version which is closest to the minor version
// of the php executable used to execute Phan .
" target_php_version " => null ,
// A list of directories that should be parsed for class and
// method information . After excluding the directories
// defined in exclude_analysis_directory_list , the remaining
// files will be statically analyzed for errors .
//
// Thus , both first - party and third - party code being used by
// your application should be included in this list .
' directory_list ' => [
' src ' ,
' vendor/symfony/console ' ,
],
// A directory list that defines files that will be excluded
// from static analysis , but whose class and method
// information should be included .
//
// Generally , you ' ll want to include the directories for
// third - party code ( such as "vendor/" ) in this list .
//
// n . b .: If you ' d like to parse but not analyze 3 rd
// party code , directories containing that code
// should be added to the `directory_list` as
// to `exclude_analysis_directory_list` .
" exclude_analysis_directory_list " => [
' vendor/ '
],
// A list of plugin files to execute .
// Plugins which are bundled with Phan can be added here by providing their name
// ( e . g . 'AlwaysReturnPlugin' )
//
// Documentation about available bundled plugins can be found
// at https : // github . com / phan / phan / tree / v5 / . phan / plugins
//
// Alternately , you can pass in the full path to a PHP file
// with the plugin ' s implementation .
// ( e . g . 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php' )
' plugins ' => [
// checks if a function , closure or method unconditionally returns .
// can also be written as 'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'
' AlwaysReturnPlugin ' ,
' DollarDollarPlugin ' ,
' DuplicateArrayKeyPlugin ' ,
' DuplicateExpressionPlugin ' ,
' PregRegexCheckerPlugin ' ,
' PrintfCheckerPlugin ' ,
' SleepCheckerPlugin ' ,
// Checks for syntactically unreachable statements in
// the global scope or function bodies .
' UnreachableCodePlugin ' ,
' UseReturnValuePlugin ' ,
' EmptyStatementListPlugin ' ,
' LoopVariableReusePlugin ' ,
],
];
자세한 내용은 구성 파일 생성 및 분석 증분 강화를 살펴보세요.
phan --help
실행하면 사용법 정보와 명령줄 옵션이 표시됩니다.
Phan은 Union 유형(예: int|MyClass|string|null
) 및 일반 배열 유형(예: int[]
또는 string[]|MyClass[]
또는 array<int,MyClass>
)을 포함한 대부분의 PHPDoc 유형 주석을 읽고 이해합니다.
코드에서 유형 정의를 시작하는 데 도움이 필요하면 소스 코드 주석 달기 및 공용체 유형 정보를 살펴보세요.
Phan은 (int|string)[]
스타일 주석을 지원하고 내부적으로 int[]|string[]
으로 표시합니다(두 주석 모두 정수 및/또는 문자열을 가질 수 있는 배열처럼 처리됩니다). 혼합된 유형의 배열이 있는 경우 array
사용하세요.
다음 코드는 지원되는 다양한 주석을 보여줍니다.
/ * *
* @ return void
* /
function f () {}
/ * * @ deprecated * /
class C {
/ * * @ var int * /
const C = 42 ;
/ * * @ var string [] | null * /
public $ p = null ;
/ * *
* @ param int | null $ p
* @ return string [] | null
* /
public static function f ( $ p ) {
if ( is_null ( $ p )) {
return null ;
}
return array_map (
/ * * @ param int $ i * /
function ( $ i ) {
return " thing $ i " ;
},
range ( 0 , $ p )
);
}
}
PHP와 마찬가지로 함수 선언에서 모든 유형을 null로 설정할 수 있으며 이는 해당 매개변수에 대해 null을 전달할 수 있음을 의미합니다.
Phan은 배열의 모든 단일 요소(키와 값 포함)의 유형을 확인합니다. 실제로 이는 [$int1=>$int2,$int3=>$int4,$int5=>$str6]
array<int,int|string>
으로 표시되고 Phan이 array<int,int>|array<int,string>
로 표시함을 의미합니다. array<int,int>|array<int,string>
. [$strKey => new MyClass(), $strKey2 => $unknown]
array<string,MyClass>|array<string,mixed>
로 표시됩니다.
[12,'myString']
과 같은 리터럴은 내부적으로 array{0:12,1:'myString'}
과 같은 배열 모양으로 표시됩니다. 이 정적 분석기는 포함을 추적하거나 자동 로더 매직을 파악하려고 시도하지 않습니다. 던지는 모든 파일을 하나의 큰 응용 프로그램으로 처리합니다. 클래스에 캡슐화된 코드의 경우 이는 잘 작동합니다. 전역 범위에서 실행되는 코드의 경우 순서가 중요하기 때문에 약간 까다로워집니다. 여러 전역 변수를 설정하는 파일이 포함된 index.php
있고 index.php
의 include(...)
뒤에 있는 항목에 액세스하려고 하면 정적 분석기는 이에 대해 아무것도 알 수 없습니다.
실용적인 측면에서 이것은 단순히 진입점과 모든 파일 설정 항목을 파일 목록 상단의 전역 범위에 넣어야 함을 의미합니다. 다른 모든 것에 필요한 전역 변수를 설정하는 config.php
있는 경우 목록에 이를 먼저 입력하고 그 다음에는 다양한 진입점을 입력한 다음 클래스를 포함하는 모든 라이브러리 파일을 입력해야 합니다.
Phan 해킹을 시작하는 데 도움이 필요하면 Phan 개발자 가이드를 살펴보세요.
문제를 발견하면 시간을 내어 버그를 설명하는 작은 재생 코드 조각을 만들어 보십시오. 그리고 일단 그것을 고치면 됩니다. 그런 다음 코드 조각을 테스트로 전환하고 이를 테스트에 추가한 다음 ./test
로 수정 및 테스트와 함께 PR을 보냅니다. 또는 세부정보가 포함된 이슈를 열 수 있습니다.
Phan의 단위 테스트를 실행하려면 ./test
실행하세요.
Phan의 모든 단위 테스트 및 통합 테스트를 실행하려면 ./tests/run_all_tests.sh
실행하세요.
우리는 환영하는 커뮤니티를 조성하기 위해 최선을 다하고 있습니다. 모든 참가자와 기여자는 당사의 행동 강령을 준수해야 합니다.
이를 위해서는 최신 버전의 Firefox/Chrome과 최소 4GB의 여유 RAM이 필요합니다. (15MB 다운로드입니다)
브라우저에서 Phan을 완전히 실행하세요.