Instead of querying the index twice (once for up-to-date files, once for
outdated ones), collect file modification timestamps during the syntactic
scan phase and use them to filter a single semantic index query.
For files that don't support syntactic scans, use the semantic index
results even if outdated.
Also extracts symlink-aware mtime resolution into URL.fileModificationDate
and exposes snapshotHasInMemoryModifications(_:) on DocumentManager.
Previously, test discovery used the semantic index as the primary
source and fell back to the syntactic index only for files where the
semantic index was out-of-date. This meant test locations came from the
semantic index, which only records a point position rather than the
full symbol range.
Flip the priority: use syntactic scan results as the primary source
(which have correct location ranges) and supplement with semantic index
results. The semantic results are range-fixed via
'textDocument/documentSymbol' before being returned.
This logic is unified into a single 'combineTests' helper shared by
both 'workspaceTests' and 'documentTests'.
Also fix 'SyntacticSwiftXCTestScanner' to emit extensions as proper
'AnnotatedTestItem' nodes (with 'isExtension: true') rather than a flat
list of methods, so extension test methods are correctly merged into
their class via 'mergingTestsInExtensions'. The class and extension
visitors are unified through a shared 'handleClassOrExtension' helper.