11import * as vscode from 'vscode' ;
2+ import * as path from 'path' ;
23import { parseDialecticUrl , DialecticUrl } from './dialecticUrl' ;
34import { searchInFile , getBestSearchResult , formatSearchResults , needsDisambiguation } from './searchEngine' ;
45
@@ -9,6 +10,115 @@ interface PlacementState {
910 wasAmbiguous : boolean ; // Whether this item had multiple possible locations
1011}
1112
13+ /**
14+ * Resolve a dialectic URL to a precise location, using placement memory and user disambiguation
15+ * Returns the resolved location without navigating to it
16+ */
17+ export async function resolveDialecticUrlPlacement (
18+ dialecticUrl : string ,
19+ outputChannel : vscode . OutputChannel ,
20+ baseUri ?: vscode . Uri ,
21+ placementMemory ?: Map < string , PlacementState >
22+ ) : Promise < { line : number ; column : number ; document : vscode . TextDocument } | null > {
23+ try {
24+ // Parse the dialectic URL to extract components
25+ const parsed = parseDialecticUrl ( dialecticUrl ) ;
26+ if ( ! parsed ) {
27+ vscode . window . showErrorMessage ( `Invalid dialectic URL: ${ dialecticUrl } ` ) ;
28+ return null ;
29+ }
30+
31+ outputChannel . appendLine ( `Resolving dialectic URL: ${ dialecticUrl } ` ) ;
32+ outputChannel . appendLine ( `Parsed components: ${ JSON . stringify ( parsed , null , 2 ) } ` ) ;
33+
34+ // Resolve the file path
35+ let resolvedPath = parsed . path ;
36+ if ( baseUri && ! path . isAbsolute ( parsed . path ) ) {
37+ resolvedPath = path . resolve ( baseUri . fsPath , parsed . path ) ;
38+ }
39+
40+ outputChannel . appendLine ( `Resolved file path: ${ resolvedPath } ` ) ;
41+
42+ // Open the document
43+ const fileUri = vscode . Uri . file ( resolvedPath ) ;
44+ const document = await vscode . workspace . openTextDocument ( fileUri ) ;
45+ let targetLine = 1 ;
46+ let targetColumn = 1 ;
47+
48+ // Handle regex search if present
49+ if ( parsed . regex ) {
50+ try {
51+ const searchResults = await searchInFile ( fileUri , { regexPattern : parsed . regex } ) ;
52+ outputChannel . appendLine ( `Search results: ${ formatSearchResults ( searchResults ) } ` ) ;
53+
54+ if ( searchResults . length === 0 ) {
55+ vscode . window . showWarningMessage ( `Regex pattern "${ parsed . regex } " not found in ${ parsed . path } ` ) ;
56+ // Fall back to line parameter if regex fails
57+ if ( parsed . line ) {
58+ targetLine = parsed . line . startLine ;
59+ targetColumn = parsed . line . startColumn || 1 ;
60+ }
61+ } else {
62+ // Check if we have a stored placement
63+ const linkKey = `link:${ dialecticUrl } ` ;
64+ const placementState = placementMemory ?. get ( linkKey ) ;
65+
66+ if ( placementState ?. isPlaced && placementState . chosenLocation ) {
67+ // Use stored placement
68+ const storedChoice = placementState . chosenLocation ;
69+ targetLine = storedChoice . line ;
70+ targetColumn = storedChoice . column ;
71+ } else if ( searchResults . length === 1 ) {
72+ // Auto-place single results (pre-disambiguated)
73+ const singleResult = searchResults [ 0 ] ;
74+ targetLine = singleResult . line ;
75+ targetColumn = singleResult . column ;
76+
77+ // Store the auto-placement
78+ placementMemory ?. set ( linkKey , {
79+ isPlaced : true ,
80+ chosenLocation : singleResult ,
81+ wasAmbiguous : false
82+ } ) ;
83+ } else {
84+ // Multiple results - show disambiguation
85+ const selectedResult = await showSearchDisambiguation ( searchResults , parsed . regex , document ) ;
86+ if ( selectedResult ) {
87+ targetLine = selectedResult . line ;
88+ targetColumn = selectedResult . column ;
89+
90+ // Store the choice
91+ placementMemory ?. set ( linkKey , {
92+ isPlaced : true ,
93+ chosenLocation : selectedResult ,
94+ wasAmbiguous : true
95+ } ) ;
96+ } else {
97+ // User cancelled disambiguation
98+ return null ;
99+ }
100+ }
101+ }
102+ } catch ( error ) {
103+ outputChannel . appendLine ( `Error during regex search: ${ error } ` ) ;
104+ vscode . window . showErrorMessage ( `Error searching for pattern "${ parsed . regex } ": ${ error } ` ) ;
105+ return null ;
106+ }
107+ } else if ( parsed . line ) {
108+ // Direct line navigation
109+ targetLine = parsed . line . startLine ;
110+ targetColumn = parsed . line . startColumn || 1 ;
111+ }
112+
113+ return { line : targetLine , column : targetColumn , document } ;
114+
115+ } catch ( error ) {
116+ outputChannel . appendLine ( `Error resolving dialectic URL: ${ error } ` ) ;
117+ vscode . window . showErrorMessage ( `Failed to resolve dialectic URL: ${ error } ` ) ;
118+ return null ;
119+ }
120+ }
121+
12122/**
13123 * Open a file location specified by a dialectic URL
14124 * Full implementation with regex search support extracted from reviewWebview
0 commit comments