diff --git a/.vscode/launch.json b/.vscode/launch.json index f700a891..cb6ce3ea 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,10 +7,14 @@ "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], "stopOnEntry": false, "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], + "outFiles": [ + "${workspaceFolder}/out/src/**/*.js" + ], "preLaunchTask": "npm" }, { @@ -18,11 +22,20 @@ "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", - "args": ["test/resources/sample.f90","--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ], + "env": { + "CODE_TESTS_WORKSPACE": "./" + }, + "args": [ + "test/resources/sample.f90", + "--disable-extensions", + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test" + ], "stopOnEntry": false, "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ], - "preLaunchTask": "npm" + "outFiles": [ + "${workspaceFolder}/out/test/**/*.js" + ] } ] -} +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e2a202a6..2bf5a454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [2.1.1] - 2019-xx-xx +## [2.2.0] - 2020-04-11 + +### Changed + +- Improve syntax highlight (#149, #166, #169) +- Fix Symbols in VSCode ^1.4x (#154, #140, #151) +- Dependencies Update (#144, #146, #155) +- Improve code completion (#148) + +### Added + +- More custom settings (#152) +- Breakpoints support (#150) + +## [2.1.1] - 2019-06-03 ### Changed diff --git a/README.md b/README.md index 2d7a1be7..0b561f16 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Installs](https://vsmarketplacebadge.apphb.com/installs/krvajalm.linter-gfortran.svg)](https://marketplace.visualstudio.com/items?itemName=krvajalm.linter-gfortran) [![GitHub release](https://img.shields.io/github/release/krvajal/vscode-fortran-support.svg)](https://GitHub.com/krvajal/vscode-fortran-support/releases/) -> This extension provides support for the Fortran programming language. It includes syntax highlighting, code snippets and a linting based on `gfortran`. You can download the Visual Studio Code editor from [here](https://code.visualstudio.com/download). +> This extension provides support for the Fortran programming language. It includes syntax highlighting, debugging, code snippets and a linting based on `gfortran`. You can download the Visual Studio Code editor from [here](https://code.visualstudio.com/download). ## Features @@ -16,6 +16,7 @@ - Code linting based on `gfortran` to show errors wiggles in your code - Code autocompletion (beta) - Symbols provider +- Debugger, uses Microsoft's [C/C++ extension](https://github.com/Microsoft/vscode-cpptools) ![symbol_nav](./doc/symbol_nav.png) @@ -23,7 +24,7 @@ You can control the include paths to be used by the linter with the `fortran.includePaths` setting. -``` +``` jsonc { "fortran.includePaths": [ "/usr/local/include", @@ -34,23 +35,23 @@ You can control the include paths to be used by the linter with the `fortran.inc By default the `gfortran` executable is assumed to be found in the path. In order to use a different one or if it can't be found in the path you can point the extension to use a custom one with the `fortran.gfortranExecutable` setting. -``` +``` jsonc { - "fortran.gfortranExecutable": '/usr/local/bin/gfortran-4.7', + "fortran.gfortranExecutable": "/usr/local/bin/gfortran-4.7", } ``` If you want to pass extra options to the `gfortran` executable or override the default one, you can use the setting `fortran.linterExtraArgs`. By default `-Wall` is the only option. -``` +``` jsonc { - "fortran.linterExtraArgs": ['-Wall'], + "fortran.linterExtraArgs": ["-Wall"], } ``` You can configure what kind of symbols will appear in the symbol list by using -``` +``` jsonc { "fortran.symbols": [ "function", "subroutine"] } @@ -68,7 +69,7 @@ and by default only functions and subroutines are shown You can also configure the case for fortran intrinsics auto-complete by using -``` +``` jsonc { "fortran.preferredCase": "lowercase" | "uppercase" } @@ -90,10 +91,65 @@ This is a list of some of the snippets included, if you like to include addition To trigger code validations you must save the file first. +## Debugging + +The extension uses the debugger from Microsoft's +[C/C++ extension](https://github.com/Microsoft/vscode-cpptools) +for Visual Studio Code. This allows this extension to use the full functionality +of the C/C++ extension for debugging applications: +(un)conditional breaking points, expression evaluation, multi-threaded debugging, +call stack, stepping, watch window. + +A minimal `launch.json` script, responsible for controlling the debugger, is +provided below. However, Visual Studio Code is also capable of autogenerating +a `launch.json` file and the configurations inside the file. + +More details about how to setup the debugger can be found in Microsoft's website: + +- General information about debugging in VS Code: +- C/C++ extension debugger information: +- Build tasks for easy compiling: + +``` jsonc +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Fortran", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/a.out", + "args": [], // Possible input args for a.out + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} +``` + ## Requirements For the linter to work you need to have `gfortran` on your path, or wherever you configure it to be. +For debugging you need to have one of the following debuggers installed: + +- **Linux**: GDB +- **macOS**: GDB or LLDB +- **Windows**: GDB or Visual Studio Windows Debugger + ## Issues Please report any issues and feature request on the GitHub repo [here](https://github.com/krvajalmiguelangel/vscode-fortran-support/issues/new) diff --git a/language-configuration.json b/language-configuration.json index 4027e926..ff54a94e 100644 --- a/language-configuration.json +++ b/language-configuration.json @@ -27,7 +27,7 @@ }, { "open": "(/", - "close": "/)" + "close": "/" } ], "surroundingPairs": [ diff --git a/package-lock.json b/package-lock.json index 18339f9a..d3478555 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "linter-gfortran", - "version": "2.0.2", + "version": "2.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -78,17 +78,6 @@ "uri-js": "^4.2.2" } }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -575,13 +564,6 @@ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", "dev": true }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, "camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", @@ -612,17 +594,6 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -720,27 +691,6 @@ } } }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - } - } - }, "clone": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", @@ -2065,7 +2015,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -2330,24 +2280,39 @@ } }, "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.3.tgz", + "integrity": "sha512-SRGwSYuNfx8DwHD/6InAPzD6RgeruWLT+B8e8a7gGs8FWgHzlExpTFMEq2IA6QpAfOClpKHy6+8IqTjeBCu6Kg==", "dev": true, "requires": { - "async": "^1.4.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" }, "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "optional": true + }, "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-js": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.0.tgz", + "integrity": "sha512-ugNSTT8ierCsDHso2jkBHXYrU8Y5/fY2ZUprfrJUiD7YpuFvV4jODLFmb3h4btQjqr5Nh4TX4XtgDfCU1WdioQ==", "dev": true, + "optional": true, "requires": { - "amdefine": ">=0.0.4" + "commander": "~2.20.3", + "source-map": "~0.6.1" } } } @@ -3135,13 +3100,6 @@ "package-json": "^4.0.0" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -3489,9 +3447,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==", "dev": true }, "lodash._basecopy": { @@ -3676,12 +3634,6 @@ "wrap-ansi": "^3.0.1" } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -3846,9 +3798,9 @@ "dev": true }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -3992,6 +3944,12 @@ } } }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4904,16 +4862,6 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.1" - } - }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -5761,34 +5709,6 @@ "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", "dev": true }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -6418,13 +6338,6 @@ "string-width": "^2.1.1" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -6493,19 +6406,6 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - }, "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/package.json b/package.json index 19bea2df..bfda8a62 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "linter-gfortran", "displayName": "Modern Fortran", "description": "Modern Fortran language support, including syntax highlighting and error detection.", - "version": "2.1.1", + "version": "2.2.0", "publisher": "krvajalm", "engines": { "vscode": "^1.30.x" @@ -15,12 +15,16 @@ "categories": [ "Programming Languages", "Snippets", - "Linters" + "Linters", + "Debuggers" ], "activationEvents": [ "onLanguage:FortranFreeForm" ], "main": "./out/src/extension", + "extensionDependencies": [ + "ms-vscode.cpptools" + ], "contributes": { "languages": [ { @@ -84,6 +88,14 @@ "path": "./snippets/fortran90.json" } ], + "breakpoints": [ + { + "language": "FortranFreeForm" + }, + { + "language": "fortran_fixed-form" + } + ], "configuration": { "type": "object", "title": "Fortran configuration", @@ -120,6 +132,11 @@ ], "description": "Specify additional options to use when calling the gfortran compiler" }, + "fortran.provideSymbols": { + "type": "boolean", + "default": true, + "description": "Enables or disables symbol functionality (disable if using 'Fortran IntelliSense')" + }, "fortran.symbols": { "type": [ "array" @@ -133,6 +150,16 @@ ], "description": "Specify what kind of symbols should be shown by the symbols' provider" }, + "fortran.provideHover": { + "type": "boolean", + "default": true, + "description": "Enables or hover functionality (disable if using 'Fortran IntelliSense')" + }, + "fortran.provideCompletion": { + "type": "boolean", + "default": true, + "description": "Enables or disables completion functionality (disable if using 'Fortran IntelliSense')" + }, "fortran.preferredCase": { "type": "string", "default": "lowercase", @@ -182,4 +209,4 @@ "dependencies": { "vscode-languageclient": "^5.1.0" } -} +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index ae17fd11..29ab86ad 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,9 +11,6 @@ import { FortranLangServer, checkForLangServer } from './lang-server' export function activate(context: vscode.ExtensionContext) { - let hoverProvider = new FortranHoverProvider() - let completionProvider = new FortranCompletionProvider() - let symbolProvider = new FortranDocumentSymbolProvider() const extensionConfig = vscode.workspace.getConfiguration(EXTENSION_ID) @@ -23,17 +20,30 @@ export function activate(context: vscode.ExtensionContext) { vscode.languages.registerCodeActionsProvider(FORTRAN_FREE_FORM_ID, linter) } - vscode.languages.registerCompletionItemProvider( - FORTRAN_FREE_FORM_ID, - completionProvider - ) - vscode.languages.registerHoverProvider(FORTRAN_FREE_FORM_ID, hoverProvider) - - vscode.languages.registerDocumentSymbolProvider( - FORTRAN_FREE_FORM_ID, - symbolProvider - ) - + if (extensionConfig.get('provideCompletion', true)) { + let completionProvider = new FortranCompletionProvider() + vscode.languages.registerCompletionItemProvider( + FORTRAN_FREE_FORM_ID, + completionProvider + ) + } + + if (extensionConfig.get('provideHover', true)) { + let hoverProvider = new FortranHoverProvider() + vscode.languages.registerHoverProvider( + FORTRAN_FREE_FORM_ID, + hoverProvider + ) + } + + if (extensionConfig.get('provideSymbols', true)) { + let symbolProvider = new FortranDocumentSymbolProvider() + vscode.languages.registerDocumentSymbolProvider( + FORTRAN_FREE_FORM_ID, + symbolProvider + ) + } + if (checkForLangServer(extensionConfig)) { const langServer = new FortranLangServer(context, extensionConfig) diff --git a/src/features/document-symbol-provider.ts b/src/features/document-symbol-provider.ts index c8e2ffa3..ae3a98eb 100644 --- a/src/features/document-symbol-provider.ts +++ b/src/features/document-symbol-provider.ts @@ -44,7 +44,6 @@ export class FortranDocumentSymbolProvider for (let i = 0; i < lines; i++) { let line: vscode.TextLine = document.lineAt(i); - line = { ...line, text: line.text.trim() }; if (line.isEmptyOrWhitespace) continue; let initialCharacter = line.text.trim().charAt(0); if (initialCharacter === "!" || initialCharacter === "#") continue; @@ -75,12 +74,12 @@ export class FortranDocumentSymbolProvider private parseSubroutineDefinition(line: TextLine) { try { - const fun = getDeclaredSubroutine(line); - if (fun) { + const subroutine = getDeclaredSubroutine(line); + if (subroutine) { let range = new vscode.Range(line.range.start, line.range.end); return new vscode.SymbolInformation( - fun.name, - vscode.SymbolKind.Method, + subroutine.name, + vscode.SymbolKind.Function, range ); } @@ -90,12 +89,11 @@ export class FortranDocumentSymbolProvider } private parseFunctionDefinition(line: TextLine) { - const subroutine = getDeclaredFunction(line); - if (subroutine) { + const fun = getDeclaredFunction(line); + if (fun) { let range = new vscode.Range(line.range.start, line.range.end); - return new vscode.SymbolInformation( - subroutine.name, + fun.name, vscode.SymbolKind.Function, range ); diff --git a/src/lib/functions.ts b/src/lib/functions.ts index b289a944..579e74c8 100644 --- a/src/lib/functions.ts +++ b/src/lib/functions.ts @@ -74,7 +74,7 @@ export const parseSubroutine = (line: TextLine) => { return _parse(line, MethodType.Subroutine); }; export const _parse = (line: TextLine, type: MethodType) => { - const functionRegEx = /([a-zA-Z]+(\([\w.=]+\))*)*\s*\bfunction\b\s*([a-zA-Z_][a-z0-9_]*)\s*\((\s*[a-z_][a-z0-9_,\s]*)*\s*(\)|\&)\s*(result\([a-z_][\w]*(\)|\&))*/i; + const functionRegEx = /(?<=([a-zA-Z]+(\([\w.=]+\))*)*)\s*\bfunction\b\s*([a-zA-Z_][a-z0-9_]*)\s*\((\s*[a-z_][a-z0-9_,\s]*)*\s*(?:\)|\&)\s*(result\([a-z_][\w]*(?:\)|\&))*/i; const subroutineRegEx = /^\s*(?!\bend\b)\w*\s*\bsubroutine\b\s*([a-z][a-z0-9_]*)\s*(?:\((\s*[a-z][a-z0-9_,\s]*)*\s*(\)|\&))*/i; const regEx = type === MethodType.Subroutine ? subroutineRegEx : functionRegEx; diff --git a/src/lib/helper.ts b/src/lib/helper.ts index dd3b7b12..824b1fcb 100644 --- a/src/lib/helper.ts +++ b/src/lib/helper.ts @@ -87,7 +87,7 @@ export const _loadDocString = (keyword: string) => { }; export const getIncludeParams = (paths: string[]) => { - return paths.map(path => `-I${path}`) + return paths.map(path => `-I${path}`); }; export function isPositionInString( diff --git a/syntaxes/fortran_free-form.tmLanguage.json b/syntaxes/fortran_free-form.tmLanguage.json index 4f6cb6b1..36a7f8ca 100644 --- a/syntaxes/fortran_free-form.tmLanguage.json +++ b/syntaxes/fortran_free-form.tmLanguage.json @@ -994,7 +994,13 @@ "include": "#if-construct" }, { - "include": "#select-construct" + "include": "#select-case-construct" + }, + { + "include": "#select-type-construct" + }, + { + "include": "#select-rank-construct" }, { "include": "#where-construct" @@ -1274,121 +1280,167 @@ } ] }, - "select-construct": { + "select-case-construct":{ + "comment": "Select case construct. Introduced in the Fortran 1990 standard.", + "begin": "(?i)\\b(select)\\s*(case)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.select.fortran" + }, + "2": { + "name": "keyword.control.case.fortran" + } + }, + "end": "(?i)(?=\\b(end\\s*select)\\b)", + "endCaptures": { + "1": { + "name": "keyword.control.endselect.fortran" + } + }, "patterns": [ { - "name": "meta.block.select.fortran", - "begin": "(?i)\\b(select)", + "include": "#parentheses" + }, + { + "begin": "(?i)\\b(case)\\b", "beginCaptures": { "1": { - "name": "keyword.control.select.fortran" + "name": "keyword.control.case.fortran" } }, - "end": "(?i)\\b(end\\s*select)\\b", - "endCaptures": { + "end": "(?i)(?=[;!\\n])", + "patterns": [ + { + "match": "(?i)\\G\\s*\\b(default)\\b", + "captures": { + "1": { + "name": "keyword.control.default.fortran" + } + } + }, + { + "include": "#parentheses" + }, + { + "include": "#invalid-word" + } + ] + }, + { + "include": "$base" + } + ] + }, + "select-type-construct":{ + "comment": "Select type construct. Introduced in the Fortran 2003 standard.", + "begin": "(?i)\\b(select)\\s*(type)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.select.fortran" + }, + "2": { + "name": "keyword.control.type.fortran" + } + }, + "end": "(?i)(?=\\b(end\\s*select)\\b)", + "endCaptures": { + "1": { + "name": "keyword.control.endselect.fortran" + } + }, + "patterns": [ + { + "include": "#parentheses" + }, + { + "begin": "(?i)\\b(?:(class)|(type))", + "beginCaptures": { "1": { - "name": "keyword.control.endselect.fortran" + "name": "keyword.control.class.fortran" + }, + "2": { + "name": "keyword.control.type.fortran" } }, + "end": "(?i)(?=[;!\\n])", "patterns": [ { - "comment": "Select case construct. Introduced in the Fortran 1990 standard.", - "begin": "(?i)\\s*(case)\\b", - "beginCaptures": { + "match": "(?i)\\G\\s*\\b(default)\\b", + "captures": { "1": { - "name": "keyword.control.case.fortran" - } - }, - "end": "(?i)(?=\\b(end\\s*select)\\b)", - "patterns": [ - { - "include": "#parentheses" - }, - { - "begin": "(?i)\\b(case)\\b", - "beginCaptures": { - "1": { - "name": "keyword.control.case.fortran" - } - }, - "end": "(?i)(?=[;!\\n])", - "patterns": [ - { - "match": "(?i)\\G\\s*\\b(default)\\b", - "captures": { - "1": { - "name": "keyword.control.default.fortran" - } - } - }, - { - "include": "#parentheses" - }, - { - "include": "#invalid-word" - } - ] - }, - { - "include": "$base" + "name": "keyword.control.default.fortran" } - ] + } }, { - "comment": "Select type construct. Introduced in the Fortran 2003 standard.", - "begin": "(?i)\\s*(type)\\b", - "beginCaptures": { + "match": "(?i)\\G\\s*(is)\\b", + "captures": { "1": { - "name": "keyword.control.type.fortran" + "name": "keyword.control.is.fortran" } - }, - "end": "(?i)(?=\\b(end\\s*select)\\b)", - "patterns": [ - { - "include": "#parentheses" - }, - { - "begin": "(?i)\\b(?:(class)|(type))", - "beginCaptures": { - "1": { - "name": "keyword.control.class.fortran" - }, - "2": { - "name": "keyword.control.type.fortran" - } - }, - "end": "(?i)(?=[;!\\n])", - "patterns": [ - { - "match": "(?i)\\G\\s*\\b(default)\\b", - "captures": { - "1": { - "name": "keyword.control.default.fortran" - } - } - }, - { - "match": "(?i)\\G\\s*(is)\\b", - "captures": { - "1": { - "name": "keyword.control.is.fortran" - } - } - }, - { - "include": "#parentheses" - }, - { - "include": "#invalid-word" - } - ] - }, - { - "include": "$base" + } + }, + { + "include": "#parentheses" + }, + { + "include": "#invalid-word" + } + ] + }, + { + "include": "$base" + } + ] + }, + "select-rank-construct":{ + "comment": "Select rank construct. Introduced in the Fortran 2008 standard.", + "begin": "(?i)\\b(select)\\s*(rank)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.select.fortran" + }, + "2": { + "name": "keyword.control.rank.fortran" + } + }, + "end": "(?i)(?=\\b(end\\s*select)\\b)", + "endCaptures": { + "1": { + "name": "keyword.control.endselect.fortran" + } + }, + "patterns": [ + { + "include": "#parentheses" + }, + { + "begin": "(?i)\\b(rank)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.rank.fortran" + } + }, + "end": "(?i)(?=[;!\\n])", + "patterns": [ + { + "match": "(?i)\\G\\s*\\b(default)\\b", + "captures": { + "1": { + "name": "keyword.control.default.fortran" } - ] + } + }, + { + "include": "#parentheses" + }, + { + "include": "#invalid-word" } ] + }, + { + "include": "$base" } ] }, @@ -1456,26 +1508,21 @@ }, "forall-construct": { "comment": "Introduced in the Fortran 1995 standard.", - "contentName": "meta.block.forall.fortran", - "begin": "(?i)\\s*\\b(forall)\\b", - "beginCaptures":{ + "begin": "(?i)\\b(forall)\\b", + "beginCaptures": { "1": { "name": "keyword.control.forall.fortran" } }, - "end": "(?i)\\s*\\b(end\\s*forall)\\b", - "endCaptures": { - "1": { - "name": "keyword.control.endforall.fortran" - } - }, - "patterns":[ + "end": "(? { test("symbol provider works as expected", async () => { - const filePath = "/test/resources/sample.f90"; - const openPath = vscode.Uri.file(`${vscode.workspace.rootPath}${filePath}`); + const filePath = path.resolve(__dirname, "../../test/resources/sample.f90"); + const openPath = vscode.Uri.file(filePath); const doc = await vscode.workspace.openTextDocument(openPath); vscode.window.showTextDocument(doc); const symbolProvider = new FortranDocumentSymbolProvider();