fortran-lang / fortls

fortls - Fortran Language Server
https://fortls.fortran-lang.org/
MIT License
258 stars 41 forks source link

robust when deal big fortran project #417

Open foranewlife opened 5 months ago

foranewlife commented 5 months ago

Is your feature request related to a problem? Please describe. Recently, I use vscode with fortls and i find a bug. When fortran project is big(like cp2k), fortls/langserver.py:1473 will use up all thread resources, as #207 shows. and parsers/internal/parser.py:2257 will show this error

  File "/home/chenys/miniforge3/lib/python3.10/site-packages/fortls/parsers/internal/parser.py", line 2257, in preprocess_file
    for include_dir in include_dirs:
RuntimeError: Set changed size during iteration

Describe the solution you'd like I fix this issue with those code.

  1. use concurrent.futures to fix using up threads pool fortls/langserver.py:1473:

    
    from concurrent.futures import ThreadPoolExecutor, as_completed
    def workspace_init(self):
        """Initialize the workspace root across multiple threads"""
    
        file_list = self._get_source_files()
        results = {}
    
        # Use ThreadPoolExecutor for better management
        with ThreadPoolExecutor(max_workers=self.nthreads) as executor:
            future_to_filepath = {
                executor.submit(
                    self.file_init,
                    filepath,
                    self.pp_defs,
                    self.pp_suffixes,
                    self.include_dirs,
                    self.sort_keywords
                ): filepath for filepath in file_list
            }
    
            for future in as_completed(future_to_filepath):
                filepath = future_to_filepath[future]
                try:
                    result_obj = future.result()
                except Exception as exc:
                    self.post_message(
                        f"Initialization failed for file {filepath}: {exc}"
                    )
                    continue
    
                if isinstance(result_obj, str):
                    self.post_message(
                        f"Initialization failed for file {filepath}: {result_obj}"
                    )
                    continue
    
                self.workspace[filepath] = result_obj
                ast_new = self.workspace[filepath].ast
                for key in ast_new.global_dict:
                    self.obj_tree[key] = [ast_new.global_dict[key], filepath]
    
        # Update include statements
        for file_obj in self.workspace.values():
            file_obj.ast.resolve_includes(self.workspace)
    
        # Update inheritance/links
        self.link_version = (self.link_version + 1) % 1000
        for file_obj in self.workspace.values():
            file_obj.ast.resolve_links(self.obj_tree, self.link_version)
2. copy a new variable to fix error.
`parsers/internal/parser.py:2257`:
```python
            include_dirs_copy = include_dirs.copy()

            for include_dir in include_dirs_copy:

Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

Additional context Add any other context or screenshots about the feature request here.