1
1
from __future__ import annotations
2
2
3
+ import logging
3
4
import os
4
5
import pprint
6
+ import sys
5
7
6
8
import json5
7
9
8
10
from .helper_functions import only_dirs , resolve_globs
9
11
from .jsonrpc import JSONRPC2Connection , ReadWriter , path_from_uri
10
12
from .langserver import LangServer
11
- from .parsers .internal .parser import FortranFile
13
+ from .parsers .internal .parser import FortranFile , preprocess_file
12
14
13
15
14
16
class DebugError (Exception ):
@@ -415,54 +417,11 @@ def debug_parser(args):
415
417
The arguments parsed from the `ArgumentParser`
416
418
"""
417
419
418
- def locate_config (root : str ) -> str | None :
419
- default_conf_files = [args .config , ".fortlsrc" , ".fortls.json5" , ".fortls" ]
420
- present_conf_files = [
421
- os .path .isfile (os .path .join (root , f )) for f in default_conf_files
422
- ]
423
- if not any (present_conf_files ):
424
- return None
425
-
426
- # Load the first config file found
427
- for f , present in zip (default_conf_files , present_conf_files ):
428
- if not present :
429
- continue
430
- config_path = os .path .join (root , f )
431
- return config_path
432
-
433
- def read_config (root : str | None ):
434
- pp_suffixes = None
435
- pp_defs = {}
436
- include_dirs = set ()
437
- if root is None :
438
- return pp_suffixes , pp_defs , include_dirs
439
-
440
- # Check for config files
441
- config_path = locate_config (root )
442
- print (f" Config file = { config_path } " )
443
- if config_path is None or not os .path .isfile (config_path ):
444
- return pp_suffixes , pp_defs , include_dirs
445
-
446
- try :
447
- with open (config_path , encoding = "utf-8" ) as fhandle :
448
- config_dict = json5 .load (fhandle )
449
- pp_suffixes = config_dict .get ("pp_suffixes" , None )
450
- pp_defs = config_dict .get ("pp_defs" , {})
451
- for path in config_dict .get ("include_dirs" , set ()):
452
- include_dirs .update (only_dirs (resolve_globs (path , root )))
453
-
454
- if isinstance (pp_defs , list ):
455
- pp_defs = {key : "" for key in pp_defs }
456
- except ValueError as e :
457
- print (f"Error { e } while parsing '{ config_path } ' settings file" )
458
-
459
- return pp_suffixes , pp_defs , include_dirs
460
-
461
420
print ("\n Testing parser" )
462
421
separator ()
463
422
464
423
ensure_file_accessible (args .debug_filepath )
465
- pp_suffixes , pp_defs , include_dirs = read_config (args .debug_rootpath )
424
+ pp_suffixes , pp_defs , include_dirs = read_config (args .debug_rootpath , args . config )
466
425
467
426
print (f' File = "{ args .debug_filepath } "' )
468
427
file_obj = FortranFile (args .debug_filepath , pp_suffixes )
@@ -482,6 +441,56 @@ def read_config(root: str | None):
482
441
separator ()
483
442
484
443
444
+ def debug_preprocessor (args ):
445
+ """Debug the preprocessor of the Language Server
446
+ Triggered by `--debug_preprocessor` option.
447
+
448
+ Parameters
449
+ ----------
450
+ args : Namespace
451
+ The arguments parsed from the `ArgumentParser`
452
+ """
453
+
454
+ def sep_lvl2 (heading : str ):
455
+ print ("\n " + "=" * 75 + f"\n { heading } \n " + "=" * 75 )
456
+
457
+ print ("\n Testing preprocessor" )
458
+ separator ()
459
+
460
+ logging .basicConfig (level = logging .DEBUG , stream = sys .stdout , format = "%(message)s" )
461
+
462
+ file = args .debug_filepath
463
+ ensure_file_accessible (file )
464
+ with open (file , encoding = "utf-8" ) as f :
465
+ lines = f .readlines ()
466
+
467
+ root = args .debug_rootpath if args .debug_rootpath else os .path .dirname (file )
468
+ _ , pp_defs , include_dirs = read_config (root , args .config )
469
+
470
+ sep_lvl2 ("Preprocessor Pass:" )
471
+ output , skips , defines , defs = preprocess_file (
472
+ lines , file , pp_defs , include_dirs , debug = True
473
+ )
474
+
475
+ sep_lvl2 ("Preprocessor Skipped Lines:" )
476
+ for line in skips :
477
+ print (f" { line } " )
478
+
479
+ sep_lvl2 ("Preprocessor Macros:" )
480
+ for key , value in defs .items ():
481
+ print (f" { key } = { value } " )
482
+
483
+ sep_lvl2 ("Preprocessor Defines (#define):" )
484
+ for line in defines :
485
+ print (f" { line } " )
486
+
487
+ sep_lvl2 ("Preprocessor Final Output:" )
488
+ for line in output :
489
+ print (rf" { line .rstrip ()} " )
490
+
491
+ separator ()
492
+
493
+
485
494
def ensure_file_accessible (filepath : str ):
486
495
"""Ensure the file exists and is accessible, raising an error if not."""
487
496
if not os .path .isfile (filepath ):
@@ -500,6 +509,51 @@ def check_request_params(args, loc_needed=True):
500
509
print (f" Char = { args .debug_char } \n " )
501
510
502
511
512
+ def locate_config (root : str , input_config : str ) -> str | None :
513
+ default_conf_files = [input_config , ".fortlsrc" , ".fortls.json5" , ".fortls" ]
514
+ present_conf_files = [
515
+ os .path .isfile (os .path .join (root , f )) for f in default_conf_files
516
+ ]
517
+ if not any (present_conf_files ):
518
+ return None
519
+
520
+ # Load the first config file found
521
+ for f , present in zip (default_conf_files , present_conf_files ):
522
+ if not present :
523
+ continue
524
+ config_path = os .path .join (root , f )
525
+ return config_path
526
+
527
+
528
+ def read_config (root : str | None , input_config : str ):
529
+ pp_suffixes = None
530
+ pp_defs = {}
531
+ include_dirs = set ()
532
+ if root is None :
533
+ return pp_suffixes , pp_defs , include_dirs
534
+
535
+ # Check for config files
536
+ config_path = locate_config (root , input_config )
537
+ print (f" Config file = { config_path } " )
538
+ if config_path is None or not os .path .isfile (config_path ):
539
+ return pp_suffixes , pp_defs , include_dirs
540
+
541
+ try :
542
+ with open (config_path , encoding = "utf-8" ) as fhandle :
543
+ config_dict = json5 .load (fhandle )
544
+ pp_suffixes = config_dict .get ("pp_suffixes" , None )
545
+ pp_defs = config_dict .get ("pp_defs" , {})
546
+ for path in config_dict .get ("include_dirs" , set ()):
547
+ include_dirs .update (only_dirs (resolve_globs (path , root )))
548
+
549
+ if isinstance (pp_defs , list ):
550
+ pp_defs = {key : "" for key in pp_defs }
551
+ except ValueError as e :
552
+ print (f"Error { e } while parsing '{ config_path } ' settings file" )
553
+
554
+ return pp_suffixes , pp_defs , include_dirs
555
+
556
+
503
557
def debug_generic (args , test_label , lsp_request , format_results , loc_needed = True ):
504
558
print (f'\n Testing "{ test_label } " request:' )
505
559
check_request_params (args , loc_needed )
0 commit comments