Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F6046172
make_stubs
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
make_stubs
View Options
#!/usr/bin/env php
<?php
declare
(
strict_types
=
1
);
use
Phan\AST\TolerantASTConverter\Shim
;
use
Phan\CodeBase
;
use
Phan\Language\Element\Clazz
;
use
Phan\Language\Element\Func
;
use
Phan\Language\Element\GlobalConstant
;
use
Phan\Language\FQSEN\FullyQualifiedClassName
;
use
Phan\Language\FQSEN\FullyQualifiedFunctionName
;
use
Phan\Language\FQSEN\FullyQualifiedGlobalConstantName
;
require_once
dirname
(
__DIR__
)
.
'/src/requirements.php'
;
require_once
dirname
(
__DIR__
)
.
'/src/Phan/Bootstrap.php'
;
// If php-ast isn't loaded already, then load this file to generate equivalent
// class, constant, and function definitions.
Shim
::
load
();
/**
* Generates PHP stubs for extensions that can be used in the autoload_internal_extension_signatures `.phan/config.php` setting.
* These are regular PHP files stubbing PHP modules, containing empty method implementations, etc.
*
* Configured stubs can be used in IDEs, analysis, etc. where extensions aren't installed or enabled (e.g. Xdebug)
* @phan-file-suppress PhanPluginDescriptionlessCommentOnPublicMethod, PhanPluginNoCommentOnPublicMethod
* @phan-file-suppress PhanPluginRemoveDebugAny
*/
class
StubsGenerator
{
/**
* @return never (does not return)
*/
public
static
function
printHelpAndExit
(
string
$message
=
''
,
int
$exit_code
=
1
)
:
void
{
if
(
$message
!==
''
)
{
echo
"$message
\n
"
;
}
global
$argv
;
$prog_name
=
$argv
[
0
];
echo
<<<EOT
Usage: $prog_name [--opts]
-h, --help
Print this help message
-e, --extension extension_name
Print stubs for only the given PECL or built in extension (e.g. 'ast', 'pcntl')
-d, --doc-comment
Include doc comments from the comment summaries bundled with Phan.
-o, --output path/to/file
Save the stubs to a file instead of printing them to stdout.
EOT;
exit
(
$exit_code
);
}
/**
* The main function of the `make_stubs` script.
* See `make_stubs --help` for usage.
*/
public
static
function
main
()
:
void
{
$options
=
getopt
(
'he:o:d'
,
[
'help'
,
'extension:'
,
'output:'
,
'doc-comment'
]);
if
(
isset
(
$options
[
'h'
])
||
isset
(
$options
[
'help'
]))
{
self
::
printHelpAndExit
(
''
,
0
);
}
if
(
isset
(
$options
[
'd'
])
||
isset
(
$options
[
'doc-comment'
]))
{
$_ENV
[
'PHAN_STUB_INCLUDE_DOC'
]
=
'1'
;
}
$code_base
=
require
(
dirname
(
__DIR__
)
.
'/src/codebase.php'
);
$extension_name
=
$options
[
'e'
]
??
$options
[
'extension'
]
??
null
;
$output_path
=
$options
[
'o'
]
??
$options
[
'output'
]
??
null
;
if
(
is_string
(
$extension_name
))
{
$output
=
self
::
generateStubsForExtension
(
$extension_name
,
$code_base
);
}
else
{
$output
=
self
::
generateAllStubs
(
$code_base
);
}
if
(
is_string
(
$output_path
))
{
file_put_contents
(
$output_path
,
$output
);
fwrite
(
STDERR
,
"Saved stubs for $extension_name to $output_path
\n
"
);
}
else
{
echo
$output
;
}
}
private
static
function
generateStubsForExtension
(
string
$extension_name
,
CodeBase
$code_base
):
string
{
$stub_collection
=
new
StubCollection
(
$code_base
);
$reflection_extension
=
new
ReflectionExtension
(
$extension_name
);
$extension_version
=
$reflection_extension
->
getVersion
();
self
::
recordClassStubsForExtension
(
$stub_collection
,
$reflection_extension
,
$code_base
);
self
::
recordGlobalFunctionStubsForExtension
(
$stub_collection
,
$reflection_extension
,
$code_base
);
self
::
recordGlobalConstantStubsForExtension
(
$stub_collection
,
$reflection_extension
,
$code_base
);
$result
=
''
;
$result
.=
"<"
.
"?php
\n
"
;
$result
.=
"// These stubs were generated by the phan stub generator.
\n
"
;
$result
.=
"// @phan-stub-for-extension $extension_name@$extension_version
\n
"
;
$result
.=
"
\n
"
;
$result
.=
$stub_collection
->
toString
();
return
$result
;
}
private
static
function
recordClassStubsForExtension
(
StubCollection
$stub_collection
,
ReflectionExtension
$reflection_extension
,
CodeBase
$code_base
)
:
void
{
foreach
(
$reflection_extension
->
getClassNames
()
as
$class_name
)
{
try
{
$class_fqsen
=
FullyQualifiedClassName
::
fromFullyQualifiedString
(
$class_name
);
}
catch
(
Exception
$e
)
{
// only possible if module info is wrong
fwrite
(
STDERR
,
"Failed to parse fqsen of class $class_name : {$e->getMessage()}
\n
"
);
continue
;
}
if
(!
$code_base
->
hasClassWithFQSEN
(
$class_fqsen
))
{
fwrite
(
STDERR
,
"Failed to find class $class_fqsen
\n
"
);
continue
;
}
$stub_collection
->
addClazz
(
$code_base
->
getClassByFQSEN
(
$class_fqsen
));
}
}
private
static
function
recordGlobalFunctionStubsForExtension
(
StubCollection
$stub_collection
,
ReflectionExtension
$reflection_extension
,
CodeBase
$code_base
)
:
void
{
foreach
(
$reflection_extension
->
getFunctions
()
as
$function_name
=>
$unused_reflection_function
)
{
try
{
$function_fqsen
=
FullyQualifiedFunctionName
::
fromFullyQualifiedString
(
$function_name
);
}
catch
(
Exception
$e
)
{
// only possible if module info is wrong
fwrite
(
STDERR
,
"Failed to parse fqsen of function $function_name : {$e->getMessage()}
\n
"
);
continue
;
}
if
(!
$code_base
->
hasFunctionWithFQSEN
(
$function_fqsen
))
{
fwrite
(
STDERR
,
"Failed to find function $function_fqsen
\n
"
);
continue
;
}
$stub_collection
->
addFunc
(
$code_base
->
getFunctionByFQSEN
(
$function_fqsen
));
}
}
private
static
function
recordGlobalConstantStubsForExtension
(
StubCollection
$stub_collection
,
ReflectionExtension
$reflection_extension
,
CodeBase
$code_base
)
:
void
{
foreach
(
$reflection_extension
->
getConstants
()
as
$constant_name
=>
$_
)
{
try
{
$const_fqsen
=
FullyQualifiedGlobalConstantName
::
fromFullyQualifiedString
(
$constant_name
);
}
catch
(
Exception
$e
)
{
// only possible if module info is invalid
fwrite
(
STDERR
,
"Failed to parse fqsen of global constant $constant_name : {$e->getMessage()}
\n
"
);
continue
;
}
if
(!
$code_base
->
hasGlobalConstantWithFQSEN
(
$const_fqsen
))
{
fwrite
(
STDERR
,
"Failed to find global constant $const_fqsen
\n
"
);
continue
;
}
$stub_collection
->
addGlobalConstant
(
$code_base
->
getGlobalConstantByFQSEN
(
$const_fqsen
));
}
}
public
static
function
generateAllStubs
(
CodeBase
$code_base
):
string
{
$code_base
->
eagerlyLoadAllSignatures
();
$stub_collection
=
new
StubCollection
(
$code_base
);
$class_map
=
$code_base
->
getInternalClassMap
();
$result
=
''
;
$result
.=
"<"
.
"?php
\n
"
;
$result
.=
"// These stubs were generated by the phan stub generator.
\n
"
;
foreach
(
$class_map
as
$class
)
{
$stub_collection
->
addClazz
(
$class
);
}
$function_map
=
$code_base
->
getFunctionMap
();
foreach
(
$function_map
as
$function
)
{
if
(
$function
->
getFQSEN
()->
isAlternate
())
{
continue
;
}
$stub_collection
->
addFunc
(
$function
);
}
$const_map
=
$code_base
->
getGlobalConstantMap
();
foreach
(
$const_map
as
$const
)
{
$stub_collection
->
addGlobalConstant
(
$const
);
}
$result
.=
$stub_collection
->
toString
();
return
$result
;
}
}
StubsGenerator
::
main
();
/**
* A representation of the collection of stubs for elements of a PHP module(a.k.a. extension).
*/
class
StubCollection
{
/** @var CodeBase represents the known state of the code base we're extracting the stubs from. */
private
$code_base
;
public
function
__construct
(
CodeBase
$code_base
)
{
$this
->
code_base
=
$code_base
;
}
/** @var string[][] a list of class stubs for a PHP module */
public
$class_stubs
=
[];
/** @var string[][] a list of function stubs for a PHP module */
public
$function_stubs
=
[];
/** @var string[][] a list of global constant stubs for a PHP module */
public
$global_constant_stubs
=
[];
public
function
addClazz
(
Clazz
$class
)
:
void
{
[
$namespace
,
$name
]
=
$class
->
toStubInfo
(
$this
->
code_base
);
$this
->
class_stubs
[
$namespace
][(
string
)
$class
->
getFQSEN
()]
=
$name
;
}
public
function
addGlobalConstant
(
GlobalConstant
$global_constant
)
:
void
{
[
$namespace
,
$name
]
=
$global_constant
->
toStubInfo
();
$this
->
global_constant_stubs
[
$namespace
][(
string
)
$global_constant
->
getFQSEN
()]
=
$name
;
}
public
function
addFunc
(
Func
$function
)
:
void
{
[
$namespace
,
$name
]
=
$function
->
toStubInfo
();
$this
->
function_stubs
[
$namespace
][(
string
)
$function
->
getFQSEN
()]
=
$name
;
}
/** @return string[][] */
public
function
toCombinedStubs
()
:
array
{
$result
=
[];
foreach
(
$this
->
class_stubs
as
$namespace
=>
$stubs
)
{
ksort
(
$stubs
,
SORT_NATURAL
);
$result
[
$namespace
]
=
array_merge
(
$result
[
$namespace
]
??
[],
$stubs
);
}
foreach
(
$this
->
function_stubs
as
$namespace
=>
$stubs
)
{
ksort
(
$stubs
,
SORT_NATURAL
);
$result
[
$namespace
]
=
array_merge
(
$result
[
$namespace
]
??
[],
$stubs
);
}
foreach
(
$this
->
global_constant_stubs
as
$namespace
=>
$stubs
)
{
ksort
(
$stubs
,
SORT_NATURAL
);
$result
[
$namespace
]
=
array_merge
(
$result
[
$namespace
]
??
[],
$stubs
);
}
return
$result
;
}
/**
* Returns the accumulated stubs converted to inline PHP code.
*/
public
function
toString
()
:
string
{
$parts
=
[];
foreach
(
$this
->
toCombinedStubs
()
as
$namespace
=>
$stubs
)
{
$concatenated_stubs_representation
=
implode
(
''
,
$stubs
);
$namespace_repr
=
(
$namespace
===
''
?
''
:
"$namespace "
);
$parts
[]
=
sprintf
(
"namespace %s{
\n
%s}
\n
"
,
$namespace_repr
,
$concatenated_stubs_representation
);
}
return
implode
(
"
\n
"
,
$parts
);
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Oct 4 2026, 21:52 (5 w, 5 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
15/12/5c2d6fccce7fb7ab8120d5e25c62
Default Alt Text
make_stubs (10 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment