Repository: fortran-lang/fortls

Issue:
Initialize Language Server Error in VScode large workspace
**Describe the bug**
Initialising Language Server Error in VScode.

**To Reproduce**
Open a large fortran workspace.

Start with posting:
```
fortls --debug_filepath mpas_atm_time_integration.F --debug_rootpath . --debug_log

Testing "initialize" request:
  Root = "."
REQUEST None None
fortls - Fortran Language Server 2.13.0 Initialized
  Successful with errors:
    fortls debugging enabled

  Source directories:
    C:\Users\****\src\core_atmosphere\dynamics
```

```
fortls --debug_filepath mpas_atm_time_integration.F --debug_rootpath . --debug_log --enable_code_actions --autocomplete_no_prefix --lowercase_intrinsics --nthreads=4 --incremental_sync

Testing "initialize" request:
  Root = "."
REQUEST None None
```

long time no output

Alternatively, you can try and describe the steps that you followed to encounter the bug:
1. Open a large fortran file
2. error on vscode output

**Setup information (please complete the following information):**
 - OS: windows
 - Python 3.11
 - fortls 2.13.0
 - Code editor used VS Code
 - Modern Fortran v3.2.0

**Configuration information (please complete the following information):**
Using default.

**VScode Log**
```
["INFO" - 14:29:50] Initialising Language Server for workspace: c:\Users\**\src\core_atmosphere\dynamics\mpas_atm_time_integration.F with command-line options: --enable_code_actions, --autocomplete_no_prefix, --lowercase_intrinsics, --nthreads=4, --incremental_sync
[Error - 14:30:11] Server initialization failed.
  Message: Error sending result: '<fortls.parse_fortran.FortranFile object at 0x000001ACEBEE63D0>'. Reason: 'RecursionError('maximum recursion depth exceeded while calling a Python object')'
  Code: -32603 
```


Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/fortran-lang/fortls/pull/373?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang) Report
Attention: Patch coverage is `83.33333%` with `1 lines` in your changes are missing coverage. Please review.
> Project coverage is 87.60%. Comparing base [(`c129c17`)](https://app.codecov.io/gh/fortran-lang/fortls/commit/c129c179ff401892e3694bd1fee8a5f05e47f45d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang) to head [(`33cc9ee`)](https://app.codecov.io/gh/fortran-lang/fortls/pull/373?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang).

| [Files](https://app.codecov.io/gh/fortran-lang/fortls/pull/373?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang) | Patch % | Lines |
|---|---|---|
| [fortls/langserver.py](https://app.codecov.io/gh/fortran-lang/fortls/pull/373?src=pr&el=tree&filepath=fortls%2Flangserver.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang#diff-Zm9ydGxzL2xhbmdzZXJ2ZXIucHk=) | 80.00% | [1 Missing :warning: ](https://app.codecov.io/gh/fortran-lang/fortls/pull/373?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #373      +/-   ##
==========================================
- Coverage   87.65%   87.60%   -0.05%     
==========================================
  Files          35       35              
  Lines        4787     4793       +6     
==========================================
+ Hits         4196     4199       +3     
- Misses        591      594       +3     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/fortran-lang/fortls/pull/373?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=fortran-lang).


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6aed22c..9b1177c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@
 
 ### Added
 
+- Added support for changing the default Python recursion depth
+  ([#312](https://github.com/fortran-lang/fortls/issues/312))
 - Added support for preprocessor macro expansions
   ([#368](https://github.com/fortran-lang/fortls/pull/368))
 - Added support for leading white spaces in preprocessor directives
diff --git a/docs/options.rst b/docs/options.rst
index c532741..b0c4d22 100644
--- a/docs/options.rst
+++ b/docs/options.rst
@@ -47,6 +47,7 @@ All the ``fortls`` settings with their default arguments can be found below
       "nthreads": 4,
       "notify_init": false,
       "incremental_sync": false,
+      "recursion_limit": 1000,
       "sort_keywords": false,
       "disable_autoupdate": false,
       "debug_log": false,
diff --git a/fortls/fortls.schema.json b/fortls/fortls.schema.json
index f6a8c09..21d421d 100644
--- a/fortls/fortls.schema.json
+++ b/fortls/fortls.schema.json
@@ -27,6 +27,12 @@
       "default": false,
       "type": "boolean"
     },
+    "recursion_limit": {
+      "title": "Recursion Limit",
+      "description": "Set the maximum recursion depth for the parser (default: 1000)",
+      "default": 1000,
+      "type": "integer"
+    },
     "sort_keywords": {
       "title": "Sort Keywords",
       "description": "Display variable keywords information, function/subroutine definitions, etc. in a consistent (sorted) manner default: no sorting, display code as is)",
diff --git a/fortls/interface.py b/fortls/interface.py
index 05cc8c1..facc99a 100644
--- a/fortls/interface.py
+++ b/fortls/interface.py
@@ -74,6 +74,13 @@ def cli(name: str = "fortls") -> argparse.ArgumentParser:
         action="store_true",
         help="Use incremental document synchronization (beta)",
     )
+    parser.add_argument(
+        "--recursion_limit",
+        type=int,
+        default=1000,
+        metavar="INTEGER",
+        help="Set the maximum recursion depth for the parser (default: %(default)s)",
+    )
     parser.add_argument(
         "--sort_keywords",
         action="store_true",
diff --git a/fortls/langserver.py b/fortls/langserver.py
index d2a9596..8ecbce1 100644
--- a/fortls/langserver.py
+++ b/fortls/langserver.py
@@ -198,6 +198,7 @@ class LangServer:
         self.source_dirs.add(self.root_path)
 
         self._load_config_file()
+        update_recursion_limit(self.recursion_limit)
         self._resolve_globs_in_paths()
         self._config_logger(request)
         self._load_intrinsics()
@@ -1593,6 +1594,7 @@ class LangServer:
             "incremental_sync", self.incremental_sync
         )
         self.sync_type: int = 2 if self.incremental_sync else 1
+        self.recursion_limit = config_dict.get("recursion_limit", self.recursion_limit)
         self.sort_keywords = config_dict.get("sort_keywords", self.sort_keywords)
         self.disable_autoupdate = config_dict.get(
             "disable_autoupdate", self.disable_autoupdate
@@ -1826,6 +1828,22 @@ class LangServer:
         return False
 
 
+def update_recursion_limit(limit: int) -> None:
+    """Update the recursion limit of the Python interpreter
+
+    Parameters
+    ----------
+    limit : int
+        New recursion limit
+
+    Examples
+    --------
+    >>> update_recursion_limit(10000)
+    """
+    if limit != sys.getrecursionlimit():
+        sys.setrecursionlimit(limit)
+
+
 class JSONRPC2Error(Exception):
     def __init__(self, code, message, data=None):
         self.code = code


Test patch:
diff --git a/test/test_interface.py b/test/test_interface.py
index 1b46f3f..764ac56 100644
--- a/test/test_interface.py
+++ b/test/test_interface.py
@@ -104,6 +104,7 @@ def test_config_file_general_options():
     assert server.incremental_sync
     assert server.sort_keywords
     assert server.disable_autoupdate
+    assert server.recursion_limit == 1500
 
 
 def test_config_file_dir_parsing_options():
diff --git a/test/test_source/f90_config.json b/test/test_source/f90_config.json
index 2d4779b..e7f9e0e 100644
--- a/test/test_source/f90_config.json
+++ b/test/test_source/f90_config.json
@@ -2,6 +2,7 @@
   "nthreads": 8,
   "notify_init": true,
   "incremental_sync": true,
+  "recursion_limit": 1500,
   "sort_keywords": true,
   "disable_autoupdate": true,