Skip to content

Commit

Permalink
fix import statement merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
wgurecky committed Apr 18, 2019
2 parents 158863a + c92fdf0 commit 3788b7a
Show file tree
Hide file tree
Showing 10 changed files with 1,741 additions and 1,066 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.pyc
.vscode
64 changes: 64 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,67 @@
## 1.8.1

### Fixes
* Fix bug with requests in lines with tab characters, fixes [#93](https://github.com/hansec/fortran-language-server/issues/93)
* Fix bug with requests following "WRITE(*,*)" statements

## 1.8.0

### Improvements
* Add full support for ASSOCIATE statements, fixes [#101](https://github.com/hansec/fortran-language-server/issues/101)
* Filter completion suggestions after "MODULE PROCEDURE" statements, fixes [#103](https://github.com/hansec/fortran-language-server/issues/103)
* Filter completion suggestions in type-bound procedure links
* Add support for including external source file directories
* Diagnostics: Line length exceeds maximum length errors
* Speedup language server initialization
* Speedup "textDocument/references" requests

## 1.7.3

### Fixes
* Fix case preservation in hover requests, fixes [#102](https://github.com/hansec/fortran-language-server/issues/102)
* Fix rename requests for type-bound procedures without an explicit link statement (ie. "=>"), fixes [#104](https://github.com/hansec/fortran-language-server/issues/104)
* Fix incorrect "CONTAINS" diagnostic errors with procedure pointers and external interfaces
* Fix bug in diagnostic construction/reporting (introduced in v1.7)
* Fix bugs caused by accidental modification of child object lists

## 1.7.2

### Fixes
* Fix bug with definition/hover requests involving intrinsic functions/modules/variables (introduced in v1.7)

## 1.7.1

### Fixes
* Fix bug with completion and signatureHelp requests on continuation lines (introduced in v1.7)
* Fix out-of-range error with various requests on zero-length lines (introduced in v1.7)

## 1.7.0

### Improvements
* Add initial support for "textDocument/codeAction" requests, generate unimplemented deferred procedures
* Show subroutine/function keywords ("PURE", "ELEMENTAL", etc.)
* Add position of object in line to "textDocument/definition" and "textDocument/implementation" results
* Diagnostics: CONTAINS statement placement errors
* Diagnostics: Visibility statement placement errors
* Command line options: Notify when workspace initialization is complete
* Command line options: Set number of threads used during initialization
* Significant refactoring of core code

### Fixes
* Fix "RecursionError" exception with circular user-defined type references, fixes [#100](https://github.com/hansec/fortran-language-server/issues/100)
* Fix bug detecting TYPE definitions with an immediately following colon, ref [#100](https://github.com/hansec/fortran-language-server/issues/100)
* Fix incorrect diagnostics for interface statements with USE instead of IMPORT statements

## 1.6.0

### Improvements
* Add support for EXTERNAL subroutines
* Diagnostics: Missing subroutine/function arguments and argument declarations
* Diagnostics: Unimplemented deferred type-bound procedures
* Diagnostics: Unknown TYPE/KIND objects (only if candidate is visible in workspace)
* Diagnostics: IMPORT statements (missing objects and placement)
* Diagnostics: Basic handling for IMPLICIT statements

## 1.5.1

### Improvements
Expand Down
28 changes: 24 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ Language Server Features
- Documentation parsing (`Doxygen <http://www.doxygen.org/>`_ and `FORD <https://github.com/Fortran-FOSS-Programmers/ford>`_ styles)
- Diagnostics (limited)

- Multiple use of the same variable name
- Unknown module in USE statement
- Variable masking definition from parent scope
- Multiple definitions with the same variable name
- Variable definition masks definition from parent scope
- Missing subroutine/function arguments
- Unknown user-defined type used in "TYPE"/"CLASS" definition (only if visible in project)
- Unclosed blocks/scopes
- Invalid scope nesting
- Contains statement errors
- Unknown modules in "USE" statement
- Unimplemented deferred type-bound procedures
- Use of unimported variables/objects in interface blocks
- Statement placement errors ("CONTAINS", "IMPLICIT", "IMPORT")

- Code actions (``textDocument/codeAction``) [Experimental]

- Generate type-bound procedures and implementation templates for deferred procedures

**Notes/Limitations:**

Expand Down Expand Up @@ -86,13 +94,18 @@ Language server settings

The following global settings can be used when launching the language server.

* ``--nthreads`` Number of threads to use during workspace initialization (default: 4)
* ``--notify_init`` Send notification message when workspace initialization is complete
* ``--symbol_skip_mem`` Do not include type members in document symbol results
* ``--incremental_sync`` Use incremental document synchronization
* ``--autocomplete_no_prefix`` Do not filter autocomplete results by variable prefix
* ``--lowercase_intrinsics`` Use lowercase for intrinsics and keywords in autocomplete requests
* ``--use_signature_help`` Use signature help instead of snippets for subroutines/functions
* ``--variable_hover`` Show hover information for variables (default: subroutines/functions only)
* ``--preserve_keyword_order`` Display variable keywords information in original order (default: sort to consistent ordering)
* ``--enable_code_actions`` Enable experimental code actions (default: false)
* ``--max_line_length`` Maximum line length (default: disabled)
* ``--max_comment_line_length`` Maximum comment line length (default: disabled)
* ``--debug_log`` Write debug information to ``root_dir/fortls_debug.log`` (requires a specified ``root_dir`` during initialization)

**Debug settings:**
Expand All @@ -114,6 +127,7 @@ The following settings can be used to perform `standalone debug tests <https://g
* ``--debug_implementation`` Test implementation request for specified file and position
* ``--debug_references`` Test references request for specified file and position
* ``--debug_rename=RENAME_STRING`` Test rename request for specified file and position
* ``--debug_actions`` Test codeAction request for specified file and position

Configuration
-------------
Expand All @@ -139,6 +153,11 @@ the ``source_dirs`` variable in the ``.fortls`` file. When ``source_dirs`` is sp
recursively, so any nested sub directories must be explicitly listed. However, ``root_dir`` does not need to
be specified manually as it is always included.

External source files (ex. libraries) can also be included in language server results by specifying their paths
in the ``ext_source_dirs`` variable in the ``.fortls`` file. These files will be parsed during initialization,
but will not be updated with any changes made until the language server is restarted. As with ``source_dirs``,
specified directories are not added recursively, so any nested sub directories must be explicitly listed.

*Note:* The previous naming convention for source file directories (``mod_dirs``) is still supported
but has been deprecated.

Expand All @@ -163,6 +182,7 @@ test can be evaluated by the server or if the region is the *default* path (ie.
"excl_paths": ["subdir3", "subdir1/file_to_skip.F90"],
"excl_suffixes": ["_skip.f90"],
"pp_defs": {"HAVE_PACKAGE": ""},
"ext_source_dirs": ["/path/to/fortran/library"],
"lowercase_intrinsics": false,
"debug_log": false
}
Expand Down
110 changes: 84 additions & 26 deletions fortls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import os
import argparse
from multiprocessing import freeze_support
from .langserver import LangServer, read_file_split
from .langserver import LangServer
from .jsonrpc import JSONRPC2Connection, ReadWriter, path_from_uri
from .parse_fortran import process_file, detect_fixed_format
__version__ = '1.5.1'
from .parse_fortran import fortran_file, process_file
__version__ = '1.8.1'


def error_exit(error_str):
Expand All @@ -23,6 +23,14 @@ def main():
'--version', action="store_true",
help="Print server version number and exit"
)
parser.add_argument(
'--nthreads', type=int, default=4,
help="Number of threads to use during workspace initialization (default: 4)"
)
parser.add_argument(
'--notify_init', action="store_true",
help="Send notification message when workspace initialization is complete"
)
parser.add_argument(
'--symbol_skip_mem', action="store_true",
help="Do not include type members in document symbol results"
Expand Down Expand Up @@ -51,6 +59,18 @@ def main():
'--preserve_keyword_order', action="store_true",
help="Display variable keywords information in original order (default: sort to consistent ordering)"
)
parser.add_argument(
'--enable_code_actions', action="store_true",
help="Enable experimental code actions (default: false)"
)
parser.add_argument(
'--max_line_length', type=int, default=-1,
help="Maximum line length (default: disabled)"
)
parser.add_argument(
'--max_comment_line_length', type=int, default=-1,
help="Maximum comment line length (default: disabled)"
)
parser.add_argument(
'--debug_log', action="store_true",
help="Generate debug log in project root folder"
Expand Down Expand Up @@ -100,6 +120,10 @@ def main():
'--debug_rename', type=str,
help="Test rename request for specified file and position"
)
group.add_argument(
'--debug_actions', action="store_true",
help="Test codeAction request for specified file and position"
)
group.add_argument(
'--debug_filepath', type=str,
help="File path for language server tests"
Expand All @@ -124,18 +148,23 @@ def main():
or args.debug_completion or args.debug_signature
or args.debug_definition or args.debug_hover
or args.debug_implementation or args.debug_references
or (args.debug_rename is not None)
or (args.debug_rename is not None) or args.debug_actions
or (args.debug_rootpath is not None)
or (args.debug_workspace_symbols is not None))
#
settings = {
"nthreads": args.nthreads,
"notify_init": args.notify_init,
"symbol_include_mem": (not args.symbol_skip_mem),
"sync_type": 2 if args.incremental_sync else 1,
"autocomplete_no_prefix": args.autocomplete_no_prefix,
"lowercase_intrinsics": args.lowercase_intrinsics,
"use_signature_help": args.use_signature_help,
"variable_hover": args.variable_hover,
"sort_keywords": (not args.preserve_keyword_order)
"sort_keywords": (not args.preserve_keyword_order),
"enable_code_actions": (args.enable_code_actions or args.debug_actions),
"max_line_length": args.max_line_length,
"max_comment_line_length": args.max_comment_line_length
}
#
if args.debug_parser:
Expand All @@ -162,23 +191,23 @@ def main():
#
print('\nTesting parser')
print(' File = "{0}"'.format(args.debug_filepath))
contents_split, err_str = read_file_split(args.debug_filepath)
if contents_split is None:
file_obj = fortran_file(args.debug_filepath)
err_str = file_obj.load_from_disk()
if err_str is not None:
error_exit("Reading file failed: {0}".format(err_str))
fixed_flag = detect_fixed_format(contents_split)
print(' Detected format: {0}'.format("fixed" if fixed_flag else "free"))
print(' Detected format: {0}'.format("fixed" if file_obj.fixed else "free"))
print("\n=========\nParser Output\n=========\n")
_, file_ext = os.path.splitext(os.path.basename(args.debug_filepath))
if file_ext == file_ext.upper():
ast_new = process_file(contents_split, True, fixed_format=fixed_flag, debug=True, pp_defs=pp_defs)
file_ast = process_file(file_obj, True, debug=True, pp_defs=pp_defs)
else:
ast_new = process_file(contents_split, True, fixed_format=fixed_flag, debug=True)
file_ast = process_file(file_obj, True, debug=True)
print("\n=========\nObject Tree\n=========\n")
for obj in ast_new.get_scopes():
for obj in file_ast.get_scopes():
print("{0}: {1}".format(obj.get_type(), obj.FQSN))
print_children(obj)
print("\n=========\nExportable Objects\n=========\n")
for _, obj in ast_new.global_dict.items():
for _, obj in file_ast.global_dict.items():
print("{0}: {1}".format(obj.get_type(), obj.FQSN))
#
elif debug_server:
Expand All @@ -193,20 +222,20 @@ def main():
if dir_exists is False:
error_exit("Specified 'debug_rootpath' does not exist or is not a directory")
print('\nTesting "initialize" request:')
print(' Root = "{0}"\n'.format(args.debug_rootpath))
print(' Root = "{0}"'.format(args.debug_rootpath))
s.serve_initialize({
"params": {"rootPath": args.debug_rootpath}
})
if len(s.post_messages) == 0:
print(" Succesful")
print(" Succesful!")
else:
print(" Succesful with errors:")
for message in s.post_messages:
print(" {0}".format(message[1]))
# Print module directories
print(" Found module directories:")
for mod_dir in s.source_dirs:
print(" {0}".format(mod_dir))
print("\n Source directories:")
for source_dir in s.source_dirs:
print(" {0}".format(source_dir))
#
if args.debug_diagnostics:
print('\nTesting "textDocument/publishDiagnostics" notification:')
Expand Down Expand Up @@ -285,9 +314,12 @@ def main():
"position": {"line": args.debug_line-1, "character": args.debug_char-1}
}
})
print(' Results:')
for obj in completion_results['items']:
print(' {0}: {1} -> {2}'.format(obj['kind'], obj['label'], obj['detail']))
if completion_results is None:
print(' No results!')
else:
print(' Results:')
for obj in completion_results:
print(' {0}: {1} -> {2}'.format(obj['kind'], obj['label'], obj['detail']))
#
if args.debug_signature:
print('\nTesting "textDocument/signatureHelp" request:')
Expand All @@ -303,8 +335,8 @@ def main():
"position": {"line": args.debug_line-1, "character": args.debug_char-1}
}
})
if len(signature_results['signatures']) == 0:
print(' No Results')
if signature_results is None:
print(' No Results!')
else:
print(' Results:')
active_param = signature_results.get('activeParameter', 0)
Expand Down Expand Up @@ -432,7 +464,7 @@ def main():
print('File: "{0}"'.format(path))
file_obj = s.workspace.get(path)
if file_obj is not None:
file_contents = file_obj['contents']
file_contents = file_obj.contents_split
for change in result:
start_line = change['range']['start']['line']
end_line = change['range']['end']['line']
Expand All @@ -444,15 +476,41 @@ def main():
line = file_contents[i]
print(' - {0}'.format(line))
if i == start_line:
new_contents.append(line[:start_col] + args.debug_rename)
new_contents.append(line[:start_col] + change['newText'])
if i == end_line:
new_contents[-1] += line[end_col:]
for line in new_contents:
print(' + {0}'.format(line))
print()
else:
print('Unknown file: "{0}"'.fromat(path))
print('Unknown file: "{0}"'.format(path))
print('=======')
#
if args.debug_actions:
import pprint
pp = pprint.PrettyPrinter(indent=2, width=120)
print('\nTesting "textDocument/getActions" request:')
check_request_params(args)
s.serve_onSave({
"params": {
"textDocument": {"uri": args.debug_filepath}
}
})
action_results = s.serve_codeActions({
"params": {
"textDocument": {"uri": args.debug_filepath},
"range": {
"start": {"line": args.debug_line-1, "character": args.debug_char-1},
"end": {"line": args.debug_line-1, "character": args.debug_char-1}
}
}
})
for result in action_results:
print("Kind = '{0}', Title = '{1}'".format(result['kind'], result['title']))
for editUri, editChange in result['edit']['changes'].items():
print("\nChange: URI = '{0}'".format(editUri))
pp.pprint(editChange)
print()
tmpout.close()
tmpin.close()
#
Expand Down
Loading

0 comments on commit 3788b7a

Please sign in to comment.