11from __future__ import annotations
22
3+ import logging
34import os
45import pprint
6+ import sys
57
68import json5
79
810from .helper_functions import only_dirs , resolve_globs
911from .jsonrpc import JSONRPC2Connection , ReadWriter , path_from_uri
1012from .langserver import LangServer
11- from .parsers .internal .parser import FortranFile
13+ from .parsers .internal .parser import FortranFile , preprocess_file
1214
1315
1416class DebugError (Exception ):
@@ -415,54 +417,11 @@ def debug_parser(args):
415417 The arguments parsed from the `ArgumentParser`
416418 """
417419
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-
461420 print ("\n Testing parser" )
462421 separator ()
463422
464423 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 )
466425
467426 print (f' File = "{ args .debug_filepath } "' )
468427 file_obj = FortranFile (args .debug_filepath , pp_suffixes )
@@ -482,6 +441,56 @@ def read_config(root: str | None):
482441 separator ()
483442
484443
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+
485494def ensure_file_accessible (filepath : str ):
486495 """Ensure the file exists and is accessible, raising an error if not."""
487496 if not os .path .isfile (filepath ):
@@ -500,6 +509,51 @@ def check_request_params(args, loc_needed=True):
500509 print (f" Char = { args .debug_char } \n " )
501510
502511
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+
503557def debug_generic (args , test_label , lsp_request , format_results , loc_needed = True ):
504558 print (f'\n Testing "{ test_label } " request:' )
505559 check_request_params (args , loc_needed )
0 commit comments