11import * as path from 'path' ;
22import { PythonProject , PythonProjectCreator , PythonProjectCreatorOptions } from '../../api' ;
33import { ProjectCreatorString } from '../../common/localize' ;
4- import { showOpenDialog } from '../../common/window.apis' ;
4+ import { showOpenDialog , showWarningMessage } from '../../common/window.apis' ;
5+ import { PythonProjectManager } from '../../internal.api' ;
6+ import { traceInfo } from '../../common/logging' ;
7+ import { Uri , window , workspace } from 'vscode' ;
8+ import { traceLog } from '../../common/logging' ;
59
610export class ExistingProjects implements PythonProjectCreator {
711 public readonly name = 'existingProjects' ;
812 public readonly displayName = ProjectCreatorString . addExistingProjects ;
913
14+ constructor ( private readonly pm : PythonProjectManager ) { }
15+
1016 async create ( _options ?: PythonProjectCreatorOptions ) : Promise < PythonProject | PythonProject [ ] | undefined > {
1117 const results = await showOpenDialog ( {
1218 canSelectFiles : true ,
@@ -19,12 +25,73 @@ export class ExistingProjects implements PythonProjectCreator {
1925 } ) ;
2026
2127 if ( ! results || results . length === 0 ) {
28+ // User cancelled the dialog & doesn't want to add any projects
2229 return ;
2330 }
2431
25- return results . map ( ( r ) => ( {
26- name : path . basename ( r . fsPath ) ,
27- uri : r ,
28- } ) ) ;
32+ // do we have any limitations that need to be applied here?
33+ // like selected folder not child of workspace folder?
34+
35+ const filtered = results . filter ( ( uri ) => {
36+ const p = this . pm . get ( uri ) ;
37+ if ( p ) {
38+ // Skip this project if there's already a project registered with exactly the same path
39+ const np = path . normalize ( p . uri . fsPath ) ;
40+ const nf = path . normalize ( uri . fsPath ) ;
41+ return np !== nf ;
42+ }
43+ return true ;
44+ } ) ;
45+
46+ if ( filtered . length === 0 ) {
47+ // No new projects found that are not already in the project manager
48+ traceInfo ( 'All discovered projects are already registered in the project manager' ) ;
49+ setImmediate ( ( ) => {
50+ showWarningMessage ( 'No new projects found' ) ;
51+ } ) ;
52+ return ;
53+ }
54+
55+ // for all the selected files / folders, check to make sure they are in the workspace
56+ const resultsOutsideWorkspace : Uri [ ] = [ ] ;
57+ const workspaceRoots : Uri [ ] = workspace . workspaceFolders ?. map ( ( w ) => w . uri ) || [ ] ;
58+ const resultsInWorkspace = filtered . filter ( ( r ) => {
59+ const exists = workspaceRoots . some ( ( w ) => r . fsPath . startsWith ( w . fsPath ) ) ;
60+ if ( ! exists ) {
61+ traceLog ( `File ${ r . fsPath } is not in the workspace, ignoring it from 'add projects' list.` ) ;
62+ resultsOutsideWorkspace . push ( r ) ;
63+ }
64+ return exists ;
65+ } ) ;
66+ if ( resultsInWorkspace . length === 0 ) {
67+ // Show a single error message with option to add to workspace
68+ const response = await window . showErrorMessage (
69+ 'Selected items are not in the current workspace.' ,
70+ 'Add to Workspace' ,
71+ 'Cancel' ,
72+ ) ;
73+
74+ if ( response === 'Add to Workspace' ) {
75+ // Use the command palette to let user adjust which folders to add
76+ // Add folders programmatically using workspace API
77+ for ( const r of resultsOutsideWorkspace ) {
78+ // if the user selects a file, add that file to the workspace
79+ await // if the user selects a folder, add that folder to the workspace
80+ await workspace . updateWorkspaceFolders (
81+ workspace . workspaceFolders ?. length || 0 , // Start index
82+ 0 , // Delete count
83+ {
84+ uri : r ,
85+ } ,
86+ ) ;
87+ }
88+ }
89+ return ;
90+ } else {
91+ return resultsInWorkspace . map ( ( uri ) => ( {
92+ name : path . basename ( uri . fsPath ) ,
93+ uri,
94+ } ) ) as PythonProject [ ] ;
95+ }
2996 }
3097}
0 commit comments