Skip to content
Permalink
Browse files

Simplify class completion lookup

Ref #1822
  • Loading branch information...
muglug committed Jun 30, 2019
1 parent 9ab3161 commit ca53019d6bb54cd6cf2e46b9cfaaa35827d94277
@@ -36,6 +36,15 @@ class Aliases
/** @var string|null */
public $namespace;
/** @var ?int */
public $namespace_first_stmt_start;
/** @var ?int */
public $uses_start;
/** @var ?int */
public $uses_end;
/**
* @param string|null $namespace
* @param array<string, string> $uses
@@ -32,6 +32,12 @@ class CodeLocation
/** @var int */
private $end_line_number = -1;
/** @var int */
public $raw_file_start;
/** @var int */
public $raw_file_end;
/** @var int */
protected $file_start;
@@ -105,6 +111,8 @@ public function __construct(
) {
$this->file_start = (int)$stmt->getAttribute('startFilePos');
$this->file_end = (int)$stmt->getAttribute('endFilePos');
$this->raw_file_start = $this->file_start;
$this->raw_file_end = $this->file_end;
$this->file_path = $file_source->getFilePath();
$this->file_name = $file_source->getFileName();
$this->single_line = $single_line;
@@ -20,6 +20,8 @@ public function __construct(
) {
$this->file_start = (int)$error->getAttributes()['startFilePos'];
$this->file_end = (int)$error->getAttributes()['endFilePos'];
$this->raw_file_start = $this->file_start;
$this->raw_file_end = $this->file_end;
$this->file_path = $file_path;
$this->file_name = $file_name;
$this->single_line = false;
@@ -353,7 +353,7 @@ public function reloadFiles(ProjectAnalyzer $project_analyzer, array $candidate_
{
$this->loadAnalyzer();
$this->file_reference_provider->loadReferenceCache();
$this->file_reference_provider->loadReferenceCache(false);
if (!$this->statements_provider->parser_cache_provider) {
$diff_files = $candidate_files;
@@ -397,6 +397,7 @@ public function reloadFiles(ProjectAnalyzer $project_analyzer, array $candidate_
$this->scanner->addFilesToDeepScan($referenced_files);
$this->addFilesToAnalyze(array_combine($candidate_files, $candidate_files));
$this->scanner->scanFiles($this->classlikes);
$this->file_reference_provider->updateReferenceCache($this, $referenced_files);
@@ -1142,7 +1143,7 @@ public function getReferenceAtPosition(string $file_path, Position $position)
}
/**
* @return array{0: string, 1: '->'|'::'|'symbol', 2: array<string, string>}|null
* @return array{0: string, 1: '->'|'::'|'symbol', 2: int}|null
*/
public function getCompletionDataAtPosition(string $file_path, Position $position)
{
@@ -1156,7 +1157,7 @@ public function getCompletionDataAtPosition(string $file_path, Position $positio
$offset = $position->toOffset($file_contents);
list($reference_map, $type_map, $alias_map) = $this->analyzer->getMapsForFile($file_path);
list($reference_map, $type_map) = $this->analyzer->getMapsForFile($file_path);
if (!$reference_map && !$type_map) {
return null;
@@ -1189,7 +1190,7 @@ public function getCompletionDataAtPosition(string $file_path, Position $positio
return null;
}
return [$recent_type, $gap, []];
return [$recent_type, $gap, $offset];
}
}
}
@@ -1202,20 +1203,7 @@ public function getCompletionDataAtPosition(string $file_path, Position $positio
if ($offset - $end_pos === 0) {
$recent_type = $possible_reference;
$found_aliases = [];
foreach ($alias_map as $aliases_start_pos => list($aliases_end_pos, $aliases)) {
if ($offset < $aliases_start_pos) {
continue;
}
if ($offset < $aliases_end_pos) {
$found_aliases = $aliases;
break;
}
}
return [$recent_type, 'symbol', $found_aliases];
return [$recent_type, 'symbol', $offset];
}
}
@@ -1311,16 +1299,52 @@ public function getCompletionItemsForClassishThing(string $type_string, string $
}
/**
* @param array<string, string> $aliases
* @return array<int, \LanguageServerProtocol\CompletionItem>
*/
public function getCompletionItemsForPartialSymbol(string $type_string, array $aliases) : array
{
public function getCompletionItemsForPartialSymbol(
string $type_string,
int $offset,
string $file_path
) : array {
$matching_classlike_names = $this->classlikes->getMatchingClassLikeNames($type_string);
$completion_items = [];
$alias_namespace = array_shift($aliases);
$file_storage = $this->file_storage_provider->get($file_path);
$aliases = null;
foreach ($file_storage->classlikes_in_file as $fq_class_name) {
try {
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
} catch (\Exception $e) {
continue;
}
if (!$class_storage->stmt_location) {
continue;
}
if ($offset > $class_storage->stmt_location->raw_file_start
&& $offset < $class_storage->stmt_location->raw_file_end
) {
$aliases = $class_storage->aliases;
break;
}
}
if (!$aliases) {
foreach ($file_storage->namespace_aliases as $namespace_start => $namespace_aliases) {
if ($namespace_start < $offset) {
$aliases = $namespace_aliases;
break;
}
}
if (!$aliases) {
$aliases = $file_storage->aliases;
}
}
foreach ($matching_classlike_names as $fq_class_name_lc) {
try {
@@ -1338,8 +1362,8 @@ public function getCompletionItemsForPartialSymbol(string $type_string, array $a
$storage->name,
Type::getStringFromFQCLN(
$storage->name,
$alias_namespace ? $alias_namespace : null,
$aliases,
$aliases && $aliases->namespace ? $aliases->namespace : null,
$aliases ? $aliases->uses_flipped : [],
null
)
);
@@ -87,15 +87,6 @@ public function collectAnalyzableInformation()
}
}
$codebase->analyzer->addNodeAliases(
$this->getFilePath(),
$this->namespace,
array_merge(
[$this->namespace_name => $this->namespace_name],
$this->getAliasedClassesFlipped()
)
);
if ($leftover_stmts) {
$statements_analyzer = new StatementsAnalyzer($this);
$context = new Context();
@@ -573,6 +573,16 @@ public static function analyze(
$statements_analyzer->getAliases()
);
if ($codebase->store_node_types && $fq_class_name) {
$codebase->analyzer->addNodeReference(
$statements_analyzer->getFilePath(),
$stmt->class,
$codebase->classlikes->classOrInterfaceExists($fq_class_name)
? $fq_class_name
: '*' . implode('\\', $stmt->class->parts)
);
}
if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
$statements_analyzer,
$fq_class_name,
@@ -583,17 +593,6 @@ public static function analyze(
return false;
}
if ($codebase->store_node_types
&& $fq_class_name
&& $codebase->classOrInterfaceExists($fq_class_name)
) {
$codebase->analyzer->addNodeReference(
$statements_analyzer->getFilePath(),
$stmt->class,
$fq_class_name
);
}
if ($codebase->alter_code) {
$codebase->classlikes->handleClassLikeReferenceInMigration(
$codebase,
@@ -61,8 +61,7 @@
* string,
* array{
* 0: TaggedCodeType,
* 1: TaggedCodeType,
* 2: array<int, array{0: int, 1: array<string, string>}>
* 1: TaggedCodeType
* }
* >,
* class_locations: array<string, array<int, \Psalm\CodeLocation>>,
@@ -152,11 +151,6 @@ class Analyzer
*/
private $type_map = [];
/**
* @var array<string, array<int, array{0: int, 1: array<string, string>}>>
*/
private $alias_map = [];
/**
* @var array<string, array<int, \Psalm\Type\Union>>
*/
@@ -440,10 +434,9 @@ function () {
FileManipulationBuffer::add($file_path, $manipulations);
}
foreach ($pool_data['file_maps'] as $file_path => list($reference_map, $type_map, $alias_map)) {
foreach ($pool_data['file_maps'] as $file_path => list($reference_map, $type_map)) {
$this->reference_map[$file_path] = $reference_map;
$this->type_map[$file_path] = $type_map;
$this->alias_map[$file_path] = $alias_map;
}
}
@@ -527,10 +520,9 @@ public function loadCachedResults(ProjectAnalyzer $project_analyzer)
$this->existing_issues = $codebase->file_reference_provider->getExistingIssues();
$file_maps = $codebase->file_reference_provider->getFileMaps();
foreach ($file_maps as $file_path => list($reference_map, $type_map, $alias_map)) {
foreach ($file_maps as $file_path => list($reference_map, $type_map)) {
$this->reference_map[$file_path] = $reference_map;
$this->type_map[$file_path] = $type_map;
$this->alias_map[$file_path] = $alias_map;
}
}
@@ -887,39 +879,6 @@ public function shiftFileOffsets(array $diff_map)
}
}
}
foreach ($this->alias_map as $file_path => &$alias_map) {
if (!isset($this->analyzed_methods[$file_path])) {
unset($this->alias_map[$file_path]);
continue;
}
$file_diff_map = $diff_map[$file_path] ?? [];
if (!$file_diff_map) {
continue;
}
$first_diff_offset = $file_diff_map[0][0];
$last_diff_offset = $file_diff_map[count($file_diff_map) - 1][1];
foreach ($alias_map as $alias_from => list($alias_to, $tag)) {
if ($alias_to < $first_diff_offset || $alias_from > $last_diff_offset) {
continue;
}
foreach ($file_diff_map as list($from, $to, $file_offset)) {
if ($alias_from >= $from && $alias_from <= $to) {
unset($alias_map[$alias_from]);
$alias_map[$alias_from += $file_offset] = [
$alias_to += $file_offset,
$tag
];
}
}
}
}
}
/**
@@ -1043,22 +1002,6 @@ public function addNodeType(
];
}
/**
* @param array<string, string> $aliases
* @return void
*/
public function addNodeAliases(
string $file_path,
PhpParser\Node $node,
array $aliases,
PhpParser\Node $parent_node = null
) {
$this->alias_map[$file_path][(int)$node->getAttribute('startFilePos')] = [
($parent_node ? (int)$parent_node->getAttribute('endFilePos') : (int)$node->getAttribute('endFilePos')) + 1,
$aliases
];
}
/**
* @return void
*/
@@ -1327,8 +1270,7 @@ public function getAnalyzedMethods()
* string,
* array{
* 0: TaggedCodeType,
* 1: TaggedCodeType,
* 2: array<int, array{0: int, 1: array<string, string>}>
* 1: TaggedCodeType
* }
* >
*/
@@ -1337,37 +1279,28 @@ public function getFileMaps()
$file_maps = [];
foreach ($this->reference_map as $file_path => $reference_map) {
$file_maps[$file_path] = [$reference_map, [], []];
$file_maps[$file_path] = [$reference_map, []];
}
foreach ($this->type_map as $file_path => $type_map) {
if (isset($file_maps[$file_path])) {
$file_maps[$file_path][1] = $type_map;
} else {
$file_maps[$file_path] = [[], $type_map, []];
}
}
foreach ($this->alias_map as $file_path => $alias_map) {
if (isset($file_maps[$file_path])) {
$file_maps[$file_path][2] = $alias_map;
} else {
$file_maps[$file_path] = [[], [], $alias_map];
$file_maps[$file_path] = [[], $type_map];
}
}
return $file_maps;
}
/**
* @return array{0: TaggedCodeType, 1: TaggedCodeType, 2: array<int, array{0: int, 1: array<string, string>}>}
* @return array{0: TaggedCodeType, 1: TaggedCodeType}
*/
public function getMapsForFile(string $file_path)
{
return [
$this->reference_map[$file_path] ?? [],
$this->type_map[$file_path] ?? [],
$this->alias_map[$file_path] ?? [],
$this->type_map[$file_path] ?? []
];
}

0 comments on commit ca53019

Please sign in to comment.
You can’t perform that action at this time.