Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1430761
FileCacheEntry.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
FileCacheEntry.php
View Options
<?php
declare
(
strict_types
=
1
);
namespace
Phan\Library
;
use
AssertionError
;
use
Microsoft\PhpParser
;
use
Microsoft\PhpParser\FilePositionMap
;
use
Phan\AST\TolerantASTConverter\CompatibleParser
;
/**
* Represents the cached contents of a given file, and various ways to access that file.
*
* This is used under the circumstances such as the following:
*
* - Checking for (at)phan-suppress-line annotations at runtime - Many checks to the same file will often be in cache
* - Checking the tokens/text of the file for purposes such as checking for expressions that are incompatible in PHP5.
* - `--automatic-fix`
*/
class
FileCacheEntry
{
/** @var string the raw file contents */
private
$contents
;
/** @var ?PhpParser\Node the raw node for the contents */
private
$ast
;
/** @var ?associative-array<int,list<PhpParser\Node>> the nodes at each line - computed lazily*/
private
$nodes_at_lines
;
/** @var ?FilePositionMap - computed lazily and shared by all fixers */
private
$file_position_map
;
/** @var ?non-empty-list<int> positions of each line (1-based) (computed lazily) */
private
$line_offset_map
=
null
;
/** @var ?associative-array<int,string> a 1-based array of lines */
private
$lines
;
/**
* Create a representation of the file contents.
*
* Other data structures are instantiated when they are first fetched.
* (different fixers would use different structures)
*/
public
function
__construct
(
string
$contents
)
{
$this
->
contents
=
$contents
;
}
/**
* Gets the raw file contents
*/
public
function
getContents
():
string
{
return
$this
->
contents
;
}
/**
* Gets the AST with all tokens (this assumes that the AST is valid)
*/
public
function
getAST
():
PhpParser\Node
{
return
$this
->
ast
??
(
$this
->
ast
=
CompatibleParser
::
create
()->
parseSourceFile
(
$this
->
contents
));
}
/**
* Get the nodes which start at a specific line number
* @return list<PhpParser\Node>
*/
public
function
getNodesAtLine
(
int
$line
):
array
{
$line_node_map
=
$this
->
nodes_at_lines
??
(
$this
->
nodes_at_lines
=
$this
->
computeNodesAtLineMap
());
return
$line_node_map
[
$line
]
??
[];
}
/**
* Compute a map from lines to the nodes at the line.
*
* This is efficient if called multiple times, but less efficient(e.g. uses more memory) if only called once.
* @return associative-array<int,list<PhpParser\Node>>
*/
public
function
computeNodesAtLineMap
():
array
{
$result
=
[];
$file_position_map
=
new
FilePositionMap
(
$this
->
contents
);
foreach
(
$this
->
getAST
()->
getDescendantNodes
()
as
$node
)
{
$line_for_node
=
$file_position_map
->
getStartLine
(
$node
);
$result
[
$line_for_node
][]
=
$node
;
}
return
$result
;
}
/**
* Fetches the shared file position map
* @suppress PhanUnreferencedPublicMethod
*/
public
function
getFilePositionMap
():
FilePositionMap
{
return
$this
->
file_position_map
??
(
$this
->
file_position_map
=
new
FilePositionMap
(
$this
->
contents
));
}
/**
* @return ?int the byte offset of the start of the given line (1-based)
* @suppress PhanUnreferencedPublicMethod
*/
public
function
getLineOffset
(
int
$line
):
?
int
{
if
(
$this
->
line_offset_map
===
null
)
{
$this
->
line_offset_map
=
self
::
computeLineOffsetMap
(
$this
->
contents
);
}
return
$this
->
line_offset_map
[
$line
]
??
null
;
}
/**
* Returns a mapping from the 1-based line number to the byte offset of the start of each line
* @internal
* @return non-empty-list<int>
*/
public
static
function
computeLineOffsetMap
(
string
$contents
):
array
{
// start of line 1 is the 0th byte
$offsets
=
[
0
,
0
];
$offset
=
0
;
while
((
$next
=
\strpos
(
$contents
,
"
\n
"
,
$offset
))
!==
false
)
{
$offset
=
$next
+
1
;
$offsets
[]
=
$offset
;
}
$offsets
[]
=
\strlen
(
$contents
);
return
$offsets
;
}
/**
* @return associative-array<int,string> a 1-based array of lines
*/
public
function
getLines
():
array
{
if
(
\is_array
(
$this
->
lines
))
{
return
$this
->
lines
;
}
$lines
=
\preg_split
(
"/^/m"
,
$this
->
contents
);
// TODO: Use a better way to not include false when arguments are both valid
if
(!
\is_array
(
$lines
))
{
throw
new
AssertionError
(
"Expected lines to be an array"
);
}
unset
(
$lines
[
0
]);
$this
->
lines
=
$lines
;
return
$lines
;
}
/**
* Helper method to get individual lines from a file.
* This is more efficient than using \SplFileObject if multiple lines may need to be fetched.
*
* @param int $lineno - A line number, starting with line 1
*/
public
function
getLine
(
int
$lineno
):
?
string
{
$lines
=
$this
->
getLines
();
return
$lines
[
$lineno
]
??
null
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 19:30 (3 h, 4 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
33/c4/836e31db2fe9138756e3812d2b54
Default Alt Text
FileCacheEntry.php (4 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment