diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index b3fb145..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 6, - "sourceType": "module", - "project":"./tsconfig.json" - }, - "plugins": [ - "@typescript-eslint" - ], - "rules": { - "@typescript-eslint/naming-convention": "warn", - "@typescript-eslint/semi": "warn", - "curly": "warn", - "eqeqeq": "warn", - "no-throw-literal": "warn", - "semi": "off", - "@typescript-eslint/no-floating-promises": "error" - }, - "ignorePatterns": [ - "out", - "dist", - "**/*.d.ts" - ] -} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 343caa3..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -out -dist -node_modules -.vscode-test/ -*.vsix -/package-lock.json -/.edkCode diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 3ac9aeb..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "dbaeumer.vscode-eslint" - ] -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 58df78a..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,45 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -// 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": "Run Extension", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ], - "preLaunchTask": "npm: compile" - }, - { - "name": "Run Extension (watch)", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}" - ], - "outFiles": [ - "${workspaceFolder}/out/**/*.js" - ] - }, - { - "name": "Extension Tests", - "type": "extensionHost", - "request": "launch", - "args": [ - "--extensionDevelopmentPath=${workspaceFolder}", - "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" - ], - "outFiles": [ - "${workspaceFolder}/out/test/**/*.js" - ], - "preLaunchTask": "npm: compile" - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 30bf8c2..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files - }, - "search.exclude": { - "out": true // set this to false to include "out" folder in search results - }, - // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 3946211..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,25 +0,0 @@ -// See https://go.microsoft.com/fwlink/?LinkId=733558 -// for the documentation about the tasks.json format -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "compile", - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "type": "npm", - "script": "watch", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": "build" - } - ] -} diff --git a/.vscodeignore b/.vscodeignore deleted file mode 100644 index 16e0171..0000000 --- a/.vscodeignore +++ /dev/null @@ -1,10 +0,0 @@ -.vscode/** -.vscode-test/** -.gitignore -.yarnrc -vsc-extension-quickstart.md -**/tsconfig.json -**/.eslintrc.json -**/*.map -**/*.ts -scripts/** diff --git a/404.html b/404.html new file mode 100755 index 0000000..3d60e42 --- /dev/null +++ b/404.html @@ -0,0 +1,138 @@ + + + + + + + + Edk2Code Vscode Extension + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • +
  • +
  • +
+
+
+
+
+ + +

404

+ +

Page not found

+ + +
+
+ +
+
+ +
+ +
+ +
+ + + + + +
+ + + + + + + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index da242e4..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,82 +0,0 @@ -# Change Log - -## [1.0.8] - -### Enhancements -- **JSON Configuration & Syntax:** - - Added new keyword pairs: `warningif`, `inconsistentif`, `disableif`, `nosubmitif` to `edk2_vfr.conf.json` and `edk2_vfr.tmLanguage.json` for improved syntax highlighting and language support. 🆕✨ - -### Bug Fixes -- **Typographical Errors:** - - Corrected misspelled words: `seeting` to `setting` and `Generationg` to `Generating`. 📝🛠️ - - Fixed a typo in the message: "c_cpp_properties.json points to wrong compile_commands.json". 📝🔧 - -### Features -- **New Commands:** - - Introduced `edk2code.copyTreeData` command to copy tree data to clipboard in a formatted string. 📋🌳 -- **Clangd Support:** - - Added support for Clang compile commands in the workspace configuration. 🛠️🔧 - - Automatically updates `clangd` configuration with the correct `--compile-commands-dir` argument if `vscode-clangd` extension is installed. 🆕🔄 - -### Code Quality -- **Refactoring & Cleanup:** - - Improved code readability by trimming redundant spaces and unifying function behavior. 🧼🛠️ - - Renamed `edksymbol.ts` to `edkSymbols.ts` for consistency. 📂🗂️ - -### Miscellaneous -- **Version Update:** - - Updated version in `package.json` from `1.0.7` to `1.0.8`. 🚀🆙 - - -All notable changes to the "edk2code" extension will be documented in this file. -## [1.0.7] - -Improvements in error handling, diagnostics, and configuration management, alongside minor updates and bug fixes. - -### Introduction of diagnostics.ts: -DiagnosticManager class and an enumeration for EDK diagnostic codes. This class manages diagnostic messages (warnings and errors) related to the EDK2 codebase. - -## [1.0.1] -- Fixed continues request to re-scan for index changes - -## [1.0.0] - -Mayor refactor to integrate optimizations -- Created specific `.edkfolder` for workspace settings.html -- Created own configuration page for workspace -- Improved autocomplete on inf files -- Improved EDK parser methods -- Removed unused code -- Added new goto commands - - -## [0.0.5] -- Fixed pattern on buildDefines configuration. This made some of the configuration options disappear - -## [0.0.4] - -### Added - -- Click on status bar now shows help of current actions -- Just EDK2 files show warnings about not being used in compilation -- Inactive symbols work with goto definition commands - -## [0.0.3] - -### Fixed - -Corrected problems that prevented the extension to run on Linux systems - -## [0.0.2] - -### Changed - -- Hide unusual commands when running in not indexed mode - -### Added - -- Use ripgrep when running in not indexed mode - -## [0.0.1] - -- Initial release. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 58dba18..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,131 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or advances of - any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, - without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -CommunityCodeOfConduct AT intel DOT com. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. - -For answers to common questions about this code of conduct, see the FAQ at -[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at -[https://www.contributor-covenant.org/translations][translations]. - -[homepage]: https://www.contributor-covenant.org -[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html -[Mozilla CoC]: https://github.com/mozilla/diversity -[FAQ]: https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index f682f4e..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,57 +0,0 @@ -# Contributing - -### License - - is licensed under the terms in [LICENSE]. By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. - -### Sign your work - -Please use the sign-off line at the end of the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify -the below (from [developercertificate.org](http://developercertificate.org/)): - -``` -Developer Certificate of Origin -Version 1.1 - -Copyright (C) 2004, 2006 The Linux Foundation and its contributors. -660 York Street, Suite 102, -San Francisco, CA 94110 USA - -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. - -Developer's Certificate of Origin 1.1 - -By making a contribution to this project, I certify that: - -(a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license - indicated in the file; or - -(b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source - license and I have the right under that license to submit that - work with modifications, whether created in whole or in part - by me, under the same open source license (unless I am - permitted to submit under a different license), as indicated - in the file; or - -(c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. - -(d) I understand and agree that this project and the contribution - are public and that a record of the contribution (including all - personal information I submit with it, including my sign-off) is - maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. -``` - -Then you just add a line to every git commit message: - - Signed-off-by: Joe Smith - -Use your real name (sorry, no pseudonyms or anonymous contributions.) - -If you set your `user.name` and `user.email` git configs, you can sign your -commit automatically with `git commit -s`. diff --git a/Images/compile-file.png b/Images/compile-file.png new file mode 100755 index 0000000..e6b8dbf Binary files /dev/null and b/Images/compile-file.png differ diff --git a/Images/discover-build-folders.png b/Images/discover-build-folders.png new file mode 100755 index 0000000..ed9ad9a Binary files /dev/null and b/Images/discover-build-folders.png differ diff --git a/Images/goto-overwrite.png b/Images/goto-overwrite.png new file mode 100755 index 0000000..5dc7b5f Binary files /dev/null and b/Images/goto-overwrite.png differ diff --git a/Images/mcp-server.png b/Images/mcp-server.png new file mode 100755 index 0000000..affb277 Binary files /dev/null and b/Images/mcp-server.png differ diff --git a/Images/module-info.png b/Images/module-info.png new file mode 100755 index 0000000..72569fb Binary files /dev/null and b/Images/module-info.png differ diff --git a/Images/settings-ui.png b/Images/settings-ui.png new file mode 100755 index 0000000..f5b831d Binary files /dev/null and b/Images/settings-ui.png differ diff --git a/Images/sidebar.png b/Images/sidebar.png new file mode 100755 index 0000000..d505064 Binary files /dev/null and b/Images/sidebar.png differ diff --git a/Images/workspace-dragdrop.png b/Images/workspace-dragdrop.png new file mode 100755 index 0000000..df9a454 Binary files /dev/null and b/Images/workspace-dragdrop.png differ diff --git a/Images/workspace-filter.png b/Images/workspace-filter.png new file mode 100755 index 0000000..5781d60 Binary files /dev/null and b/Images/workspace-filter.png differ diff --git a/Images/workspace-reveal.png b/Images/workspace-reveal.png new file mode 100755 index 0000000..3ffdeb3 Binary files /dev/null and b/Images/workspace-reveal.png differ diff --git a/Images/workspace-search.png b/Images/workspace-search.png new file mode 100755 index 0000000..e39630e Binary files /dev/null and b/Images/workspace-search.png differ diff --git a/Images/workspace-select.png b/Images/workspace-select.png new file mode 100755 index 0000000..cfdf0b4 Binary files /dev/null and b/Images/workspace-select.png differ diff --git a/Images/workspace-view.png b/Images/workspace-view.png new file mode 100755 index 0000000..c0877a6 Binary files /dev/null and b/Images/workspace-view.png differ diff --git a/Images/workspace-welcome.png b/Images/workspace-welcome.png new file mode 100755 index 0000000..0b096cf Binary files /dev/null and b/Images/workspace-welcome.png differ diff --git a/Index-source-code/index.html b/Index-source-code/index.html new file mode 100755 index 0000000..9ba9725 --- /dev/null +++ b/Index-source-code/index.html @@ -0,0 +1,214 @@ + + + + + + + + Quick start - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ +

Quick start

+

Most of the extension functionality will work out of the box on any given EDK2 project. However it will have the full set of features enabled when the source code is compiled and the workspace is loaded.

+

Loading the workspace

+

When you open a folder that contains an EDK2 project, look for the Edk2Code icon in the activity bar on the left side of VS Code. Clicking it opens the Edk2Code sidebar, which contains the Workspace and Module Info views.

+

Edk2Code sidebar

+

The Workspace view will guide you through loading your build configuration. If nothing is loaded yet, you will see the welcome screen:

+

Workspace welcome view

+ +

If you have already compiled your EDK2 project, click Discover Build Folders. The extension will scan your workspace and detect all existing build output folders automatically.

+

Once discovery completes, click Use discovered folders to load the detected configurations. The Workspace view will populate with your DSC, INF, and source file hierarchy.

+

You can also trigger this at any time from the command palette:

+
> EDK2: Discover build folders
+> EDK2: Use discovered build folders
+
+

Option 2 — Manual configuration

+

Click Open EDK2 Configuration (or run EDK2: Workspace configuration (UI)) to open the settings panel and manually specify:

+
    +
  • DSC paths — the main .dsc files for your platform
  • +
  • Build Defines — any -D flags used in your build command
  • +
  • Package paths — extra package roots passed to the build
  • +
+
> EDK2: Workspace configuration (UI)
+
+

Rebuild / Rescan

+

To force a full re-index after a new build, use:

+
> EDK2: Rebuild index database
+
+

To reload using the existing configuration without changing any settings:

+
> EDK2: Rescan index database
+
+

Enable compile information

+

You can use the compile information build feature from EDK2 to provide more build information to the extension. This is optional but recommended

+

To enable the compile information you need to enable the build report flag in the EDK2 build command and set -Y COMPILE_INFO. You can check more information about EDK build process here

+

For example, if you want to build EmulatorPkg from EDK2 source, your build command will look like this:

+
build -p EmulatorPkg\EmulatorPkg.dsc -t VS2019 -a IA32 -Y COMPILE_INFO -y BuildReport.log
+
+

This will generate compile information in your build folder.

+

-Y COMPILE_INFO -y BuildReport.log will add to your build folder the CompileInfo folder:

+

x:\Edk2\Build\EmulatorIA32\DEBUG_VS2019\CompileInfo

+

Files produced after parsing

+

After parsing is completed, some files will be created in .edkCode folder on your workspace.

+

.ignore

+

This is a list of all your the files in your source that were not used during compilation. The generation of this file can be disabled in the extension settings. This file is used by VSCODE to ignore unused files. You can toggle the use of .ignore file in search:

+

Search ignore

+

compile_commands.json

+

This is the compilation database generated during build process. You can setup your C/C++ VSCODE plugging to use this compilation database to get better C parsing.

+

To setup compile commands in your workspace, open C/C++: edit configurations (UI) in command palette. Under Advance Settings look for Compile commands property. Set the path for ${workspaceFolder}\.edkCode\compile_commands.json as shown in the following image:

+

Compile commands

+

The EDK2Code extension will detect if compile_commands.json exists and will prompt the user to update the configuration

+

cscope.files

+

This is the list of all your files used in compilation. This file is used by Cscope to help provide C definitions.

+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + Next » + + +
+ + + + + + + + + + + + + + diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index a9039f7..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2025 Intel Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 82831e8..0000000 --- a/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# EDK2Code Extension for Visual Studio Code - -The EDK2Code Extension is a Visual Studio Code extension designed to improve the development experience for engineers working with the EDK2 (UEFI) codebase. This extension provides support for syntax highlighting, code navigation, and error detection for the EDK2 language. By integrating these features directly into Visual Studio Code, developers can streamline their workflow and enhance productivity. - -Check YouTube vide presentation on UEFIForum Channel - -[![YouTube presentation](https://img.youtube.com/vi/2Js9nSPKtd8/0.jpg)](https://www.youtube.com/watch?v=2Js9nSPKtd8) - -![](assets/demo.gif) - -![](assets/demo_dsc.gif) - -It also includes some support for ASL language: - -![](assets/demo_acpi.gif) - -## Features - -- Syntax highlighting for EDK2 files. -- Code navigation, including "Go to Definition" and "Find All References" for EDK2 symbols. -- Error detection and reporting for common EDK2 language issues. -- Auto-completion for EDK2 keywords and symbols. - -## Installation - -1. Open Visual Studio Code. -2. Navigate to the Extensions view by clicking the square icon on the left sidebar or pressing `Ctrl+Shift+X`. -3. Search for "EDK2Code" in the search bar. -4. Click the "Install" button on the extension's card. -5. Reload Visual Studio Code to activate the extension. - -### Linux Installation - -[Cscope](https://cscope.sourceforge.net/) is used for some C related functionality of the extension. On windows systems the cscope comes already included in the extension. - -For linux systems you need to install cscope`manually. - -Ubuntu installation example: `sudo apt install cscope` - -## Documentation - -Check full documentation including setup on [project home page](https://intel.github.io/Edk2Code/) - - -## Contributing - -If you would like to contribute to the development of the EDK2Code Extension, please visit the [GitHub repository](https://github.com/intel/Edk2Code) for more information on how to submit issues, feature requests, or pull requests. - - -## Support - -For support or questions regarding the EDK2Code Extension, please create an issue in the [GitHub repository](https://github.com/intel/Edk2Code/issues). diff --git a/assets/demo.gif b/assets/demo.gif deleted file mode 100644 index 69fa878..0000000 Binary files a/assets/demo.gif and /dev/null differ diff --git a/assets/demo_acpi.gif b/assets/demo_acpi.gif deleted file mode 100644 index 64ccf4d..0000000 Binary files a/assets/demo_acpi.gif and /dev/null differ diff --git a/assets/demo_dsc.gif b/assets/demo_dsc.gif deleted file mode 100644 index c10108d..0000000 Binary files a/assets/demo_dsc.gif and /dev/null differ diff --git a/assets/icon.png b/assets/icon.png deleted file mode 100644 index ceb399a..0000000 Binary files a/assets/icon.png and /dev/null differ diff --git a/css/fonts/Roboto-Slab-Bold.woff b/css/fonts/Roboto-Slab-Bold.woff new file mode 100755 index 0000000..6cb6000 Binary files /dev/null and b/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/css/fonts/Roboto-Slab-Bold.woff2 b/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100755 index 0000000..7059e23 Binary files /dev/null and b/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/css/fonts/Roboto-Slab-Regular.woff b/css/fonts/Roboto-Slab-Regular.woff new file mode 100755 index 0000000..f815f63 Binary files /dev/null and b/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/css/fonts/Roboto-Slab-Regular.woff2 b/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100755 index 0000000..f2c76e5 Binary files /dev/null and b/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/css/fonts/fontawesome-webfont.eot b/css/fonts/fontawesome-webfont.eot new file mode 100755 index 0000000..e9f60ca Binary files /dev/null and b/css/fonts/fontawesome-webfont.eot differ diff --git a/css/fonts/fontawesome-webfont.svg b/css/fonts/fontawesome-webfont.svg new file mode 100755 index 0000000..855c845 --- /dev/null +++ b/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/css/fonts/fontawesome-webfont.ttf b/css/fonts/fontawesome-webfont.ttf new file mode 100755 index 0000000..35acda2 Binary files /dev/null and b/css/fonts/fontawesome-webfont.ttf differ diff --git a/css/fonts/fontawesome-webfont.woff b/css/fonts/fontawesome-webfont.woff new file mode 100755 index 0000000..400014a Binary files /dev/null and b/css/fonts/fontawesome-webfont.woff differ diff --git a/css/fonts/fontawesome-webfont.woff2 b/css/fonts/fontawesome-webfont.woff2 new file mode 100755 index 0000000..4d13fc6 Binary files /dev/null and b/css/fonts/fontawesome-webfont.woff2 differ diff --git a/css/fonts/lato-bold-italic.woff b/css/fonts/lato-bold-italic.woff new file mode 100755 index 0000000..88ad05b Binary files /dev/null and b/css/fonts/lato-bold-italic.woff differ diff --git a/css/fonts/lato-bold-italic.woff2 b/css/fonts/lato-bold-italic.woff2 new file mode 100755 index 0000000..c4e3d80 Binary files /dev/null and b/css/fonts/lato-bold-italic.woff2 differ diff --git a/css/fonts/lato-bold.woff b/css/fonts/lato-bold.woff new file mode 100755 index 0000000..c6dff51 Binary files /dev/null and b/css/fonts/lato-bold.woff differ diff --git a/css/fonts/lato-bold.woff2 b/css/fonts/lato-bold.woff2 new file mode 100755 index 0000000..bb19504 Binary files /dev/null and b/css/fonts/lato-bold.woff2 differ diff --git a/css/fonts/lato-normal-italic.woff b/css/fonts/lato-normal-italic.woff new file mode 100755 index 0000000..76114bc Binary files /dev/null and b/css/fonts/lato-normal-italic.woff differ diff --git a/css/fonts/lato-normal-italic.woff2 b/css/fonts/lato-normal-italic.woff2 new file mode 100755 index 0000000..3404f37 Binary files /dev/null and b/css/fonts/lato-normal-italic.woff2 differ diff --git a/css/fonts/lato-normal.woff b/css/fonts/lato-normal.woff new file mode 100755 index 0000000..ae1307f Binary files /dev/null and b/css/fonts/lato-normal.woff differ diff --git a/css/fonts/lato-normal.woff2 b/css/fonts/lato-normal.woff2 new file mode 100755 index 0000000..3bf9843 Binary files /dev/null and b/css/fonts/lato-normal.woff2 differ diff --git a/css/theme.css b/css/theme.css new file mode 100755 index 0000000..ad77300 --- /dev/null +++ b/css/theme.css @@ -0,0 +1,13 @@ +/* + * This file is copied from the upstream ReadTheDocs Sphinx + * theme. To aid upgradability this file should *not* be edited. + * modifications we need should be included in theme_extra.css. + * + * https://github.com/readthedocs/sphinx_rtd_theme + */ + + /* sphinx_rtd_theme version 1.2.0 | MIT license */ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} diff --git a/css/theme_extra.css b/css/theme_extra.css new file mode 100755 index 0000000..ab0631a --- /dev/null +++ b/css/theme_extra.css @@ -0,0 +1,197 @@ +/* + * Wrap inline code samples otherwise they shoot of the side and + * can't be read at all. + * + * https://github.com/mkdocs/mkdocs/issues/313 + * https://github.com/mkdocs/mkdocs/issues/233 + * https://github.com/mkdocs/mkdocs/issues/834 + */ +.rst-content code { + white-space: pre-wrap; + word-wrap: break-word; + padding: 2px 5px; +} + +/** + * Make code blocks display as blocks and give them the appropriate + * font size and padding. + * + * https://github.com/mkdocs/mkdocs/issues/855 + * https://github.com/mkdocs/mkdocs/issues/834 + * https://github.com/mkdocs/mkdocs/issues/233 + */ +.rst-content pre code { + white-space: pre; + word-wrap: normal; + display: block; + padding: 12px; + font-size: 12px; +} + +/** + * Fix code colors + * + * https://github.com/mkdocs/mkdocs/issues/2027 + */ +.rst-content code { + color: #E74C3C; +} + +.rst-content pre code { + color: #000; + background: #f8f8f8; +} + +/* + * Fix link colors when the link text is inline code. + * + * https://github.com/mkdocs/mkdocs/issues/718 + */ +a code { + color: #2980B9; +} +a:hover code { + color: #3091d1; +} +a:visited code { + color: #9B59B6; +} + +/* + * The CSS classes from highlight.js seem to clash with the + * ReadTheDocs theme causing some code to be incorrectly made + * bold and italic. + * + * https://github.com/mkdocs/mkdocs/issues/411 + */ +pre .cs, pre .c { + font-weight: inherit; + font-style: inherit; +} + +/* + * Fix some issues with the theme and non-highlighted code + * samples. Without and highlighting styles attached the + * formatting is broken. + * + * https://github.com/mkdocs/mkdocs/issues/319 + */ +.rst-content .no-highlight { + display: block; + padding: 0.5em; + color: #333; +} + + +/* + * Additions specific to the search functionality provided by MkDocs + */ + +.search-results { + margin-top: 23px; +} + +.search-results article { + border-top: 1px solid #E1E4E5; + padding-top: 24px; +} + +.search-results article:first-child { + border-top: none; +} + +form .search-query { + width: 100%; + border-radius: 50px; + padding: 6px 12px; + border-color: #D1D4D5; +} + +/* + * Improve inline code blocks within admonitions. + * + * https://github.com/mkdocs/mkdocs/issues/656 + */ + .rst-content .admonition code { + color: #404040; + border: 1px solid #c7c9cb; + border: 1px solid rgba(0, 0, 0, 0.2); + background: #f8fbfd; + background: rgba(255, 255, 255, 0.7); +} + +/* + * Account for wide tables which go off the side. + * Override borders to avoid weirdness on narrow tables. + * + * https://github.com/mkdocs/mkdocs/issues/834 + * https://github.com/mkdocs/mkdocs/pull/1034 + */ +.rst-content .section .docutils { + width: 100%; + overflow: auto; + display: block; + border: none; +} + +td, th { + border: 1px solid #e1e4e5 !important; + border-collapse: collapse; +} + +/* + * Without the following amendments, the navigation in the theme will be + * slightly cut off. This is due to the fact that the .wy-nav-side has a + * padding-bottom of 2em, which must not necessarily align with the font-size of + * 90 % on the .rst-current-version container, combined with the padding of 12px + * above and below. These amendments fix this in two steps: First, make sure the + * .rst-current-version container has a fixed height of 40px, achieved using + * line-height, and then applying a padding-bottom of 40px to this container. In + * a second step, the items within that container are re-aligned using flexbox. + * + * https://github.com/mkdocs/mkdocs/issues/2012 + */ + .wy-nav-side { + padding-bottom: 40px; +} + +/* For section-index only */ +.wy-menu-vertical .current-section p { + background-color: #e3e3e3; + color: #404040; +} + +/* + * The second step of above amendment: Here we make sure the items are aligned + * correctly within the .rst-current-version container. Using flexbox, we + * achieve it in such a way that it will look like the following: + * + * [No repo_name] + * Next >> // On the first page + * << Previous Next >> // On all subsequent pages + * + * [With repo_name] + * Next >> // On the first page + * << Previous Next >> // On all subsequent pages + * + * https://github.com/mkdocs/mkdocs/issues/2012 + */ +.rst-versions .rst-current-version { + padding: 0 12px; + display: flex; + font-size: initial; + justify-content: space-between; + align-items: center; + line-height: 40px; +} + +/* + * Please note that this amendment also involves removing certain inline-styles + * from the file ./mkdocs/themes/readthedocs/versions.html. + * + * https://github.com/mkdocs/mkdocs/issues/2012 + */ +.rst-current-version span { + flex: 1; + text-align: center; +} diff --git a/documentation/Settings/index.html b/documentation/Settings/index.html new file mode 100755 index 0000000..cde81f5 --- /dev/null +++ b/documentation/Settings/index.html @@ -0,0 +1,181 @@ + + + + + + + + Extension settings - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Extension settings

+

Edk2code: Log Level

+

Used to debug the extension development. Its recommended to keep on None unless you are debugging the Edk2Code extension.

+
+

Edk2code: Generate Ignore File

+

Generates .ignore file as part of source index process

+
+

Edk2code: Use Cscope

+

Enable or disable cscope integration. When disabled, the cscope database will not be built or queried, and features that depend on it (call hierarchy, cscope-based Go to definition) will be unavailable.

+

A reload of VS Code is required after changing this setting.

+
+

Edk2code: Mcp Server Port

+

Port number used by the MCP SSE server started with EDK2: Start MCP SSE Server.

+

Default: 3100.

+
+

Edk2code: Cscope Overwrite Path

+

Overwrites the path used to invoke the cscope executable. Leave empty to use the one available on PATH.

+

A reload of VS Code is required after changing this setting.

+
+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + Next » + + +
+ + + + + + + + + + + + + + diff --git a/documentation/Workspace-settings/index.html b/documentation/Workspace-settings/index.html new file mode 100755 index 0000000..4489f79 --- /dev/null +++ b/documentation/Workspace-settings/index.html @@ -0,0 +1,188 @@ + + + + + + + + Workspace settings - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Workspace settings

+

The workspace configuration controls which DSC files, build defines, and package paths the extension uses when parsing your EDK2 project.

+

Configuration UI

+

The easiest way to manage the workspace settings is through the graphical configuration panel. Open it from the Workspace view title bar ($(gear) icon) or via the command palette:

+
> EDK2: Workspace configuration (UI)
+
+

Workspace settings UI

+

The panel lets you set:

+
    +
  • DSC paths — the main .dsc files for your platform (relative to the workspace root).
  • +
  • Build Defines — definitions injected in your build command with -D (e.g. ARCH=X64).
  • +
  • Package paths — additional package roots passed to the EDK2 build.
  • +
+

Configuration file

+

The settings are stored in .edkCode/edk2_workspace_properties.json inside your workspace. You can also edit this file directly or open it with:

+
> EDK2: Workspace configuration (JSON)
+
+
{
+    "packagePaths": [],
+    "dscPaths": [
+        "OvmfPkg\\OvmfPkgX64.dsc"
+    ],
+    "buildDefines": [
+        "ARCH=X64"
+    ]
+}
+
+

dscPaths — Each entry should be a main DSC file used for compilation.

+

buildDefines — Definitions injected in your build command with -D. Add or modify entries to match your build.

+
+

After any modification to this file, VS Code will prompt you to reload the index.

+
+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + Next » + + +
+ + + + + + + + + + + + + + diff --git a/documentation/documentation/index.html b/documentation/documentation/index.html new file mode 100755 index 0000000..a8b509a --- /dev/null +++ b/documentation/documentation/index.html @@ -0,0 +1,490 @@ + + + + + + + + Documentation - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Documentation

+

Before you start testing the functionality of the extension, please index your source code.

+

Configuration

+

You can check your workspace configuration with command:

+
> EDK2: Workspace configuration (UI)
+
+

This configuration will be automatically populated after you indexed your source code.

+
    +
  • DSC relative path Are the main DSC files for your workspace
  • +
  • Build Defines Build defines that were injected in your EDK2 build command
  • +
  • Package paths are the paths set for the EDK2 Build command.
  • +
+

You can manually change this configuration. After any manual modification the user will be prompted to rescan the Index.

+

Interface

+

Status bar

+

When you open a file in the editor, you will see in the status bar a warning if the file you are looking has been compiled or not:

+

Status bar

+

The following commands are expected to work only on files that have been used in compilation.

+

Global commands

+

This commands are only accessible using the command palette (⌨F1)

+

EDK2: Open library

+

Will show a list of all the libraries compiled.

+

Open library

+

EDK2: Open Module

+

Will show a list of all the modules compiled.

+

EDK2: Rebuild index database

+

This will clean up the current source index and will create a new one. See Quick start for details.

+

EDK2: Rescan index database

+

This will use the previous index configuration and will recreate the index without changing the workspace settings

+

EDK2 language support

+

After you source code has been indexed you will see some of the features of using Edk2Code extension

+
+

⚠ IMPORTANT Before continuing please index your code following this instructions

+
+

INF files

+

Inf files will show syntax highlight:

+

image

+

Outline tree

+

Outline tree

+

Source goto definition

+

Right click on a source file name and then select Go To Definition (F12)

+

Go to Definition

+

This will open the source file selected. This also works for LibraryClasses, Pcd and Packages:

+

Goto Library

+

The results shown are based on your DSC parsing.

+

LibraryClasses Auto completion

+

Start typing on the LibraryClasses section will show suggestions of libraries that can be included in that INF file:

+

Auto complete

+

This suggestions are based on DEC files in Packages section.

+

Goto DSC Declaration

+

Right click on an anywhere in an INF file and select EDK2: Goto DSC Declaration

+

Go to DSC

+

This will open the DSC file where this INF file was declared.

+

Library usage

+

If the INF file is a library, right click and select EDK2: Show Library usage:

+

image

+

This will show what modules are using your library:

+

Library usage

+

DSC Files

+

Syntax highlight

+

DSC files have full syntax highlighting for sections, conditionals (!if, !else, !endif), includes (!include), macros, PCDs, and module entries.

+

Outline

+

The Outline view shows all sections ([LibraryClasses], [Components], [PcdsFixedAtBuild], etc.) and their entries, allowing quick navigation within large DSC files.

+

Variable defines resolution

+

DSC files will dim source that hasn't been compiled based on DEFINES. +You can see the value of the defines if you hover your mouse over.

+

This also works with PCD values

+

Variable resolution

+

Goto Definition

+

Right click on a file path and select Go to Definition (F12) to open that file.

+

Goto DSC inclusion

+

Right click and select Go to DSC Inclusion to see if this DSC file was included (!Include) in other DSC file.

+

DEC

+

Syntax highlight

+

DEC files have syntax highlighting for section headers, GUID definitions, PCD declarations, library class definitions, and include paths.

+

Outline

+

The Outline view shows all sections ([Guids], [Protocols], [Ppis], [LibraryClasses], [Pcds*], etc.) for easy navigation.

+

C files

+

Call Hierarchy

+

Right on a function name and select Show Call Hierarchy:

+

image

+

This will open the References view with the call Hierarchy of the selected function. Edk2Code extension will filter unused calls from the view.

+

image

+

Go to INF

+

When you are on a C file, Right click and select Go to INF:

+

image

+

This will open the .inf file that compiled that C file.

+

Go to Definition

+

Right click on a C symbol (function, variable, etc) and select EDK2: Go To Definition to open the symbol definition. This differs from regular Go to Definition command provided by VSCODE as this will uses CSCOPE and compiled files to query the definitions. Sometimes it gives better results.

+

VFR

+

Syntax highlight

+

VFR (Visual Forms Representation) files have syntax highlighting for form definitions, questions, one-of selections, checkboxes, strings, and other HII form elements.

+

Outline

+

The Outline view shows the form set, individual forms, and their question elements, making it easy to navigate complex VFR layouts.

+

ACPI

+

Syntax highlight

+

ASL (ACPI Source Language) files have syntax highlighting for device definitions, methods, operators, named objects, and resource descriptors.

+

Outline

+

The Outline view shows the ASL definition block structure including devices, methods, scopes, and named objects for easy navigation.

+

Help

+

Hover on keywords of your ASL code and you will see help extracted from ACPI specification (6.3)

+

image

+

Auto complete

+

Start typing anywhere in your *.asl files and you will see autocomplete suggestions of ASL specification.

+

image

+

Edk2Code sidebar

+

Starting in version 2.0.0, the extension installs its own activity bar container. All Edk2Code views are grouped under this entry, which exposes two views: Workspace and Module Info.

+

Edk2Code sidebar

+

Workspace view

+

The Workspace view shows your parsed EDK2 workspace as a single, persistent tree. It replaces the older Module Map, Library Tree and Reference Tree commands with one navigable hierarchy of DSC → INF → libraries / sources / headers.

+

Workspace view

+

When no workspace is loaded yet, the welcome view offers quick actions to discover build folders or open the configuration UI.

+

Workspace welcome

+

The view title bar exposes the following actions:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ActionCommandDescription
$(gear)EDK2: Workspace configuration (UI)Open the graphical configuration panel.
$(repo)EDK2: Select WorkspaceSwitch between loaded build configurations.
$(target)EDK2: Reveal active editor in workspace treeLocate the active file in the tree.
$(search)EDK2: Search workspace treeFind a node by name.
$(filter)EDK2: Filter workspace symbolsHide grayed-out / inactive elements.
$(copy)EDK2: Copy workspace treeCopy the tree (or a sub-tree) as text.
$(refresh)EDK2: Refresh workspace configReload the workspace configuration.
$(close)EDK2: Unload workspaceClear the currently loaded configuration.
+

Additional capabilities:

+
    +
  • Drag and drop to rearrange tree nodes.
  • +
  • Right-click → Copy path on any node.
  • +
  • Searching for symbols from the command palette will automatically switch to the workspace that owns the result.
  • +
+

Workspace search

+

Module Info view

+

The Module Info view shows EDK2 module information for the file currently open in the editor. As soon as you open a C, INF or related source file that belongs to a module, the view populates with:

+
    +
  • The owning INF and its DSC declaration
  • +
  • Libraries linked to the module
  • +
  • Quick navigation actions (go to definition, open file, go to DSC declaration)
  • +
+

Double-click any entry to jump directly to the corresponding source location.

+

Module Info view

+

Build folder auto-discovery

+

EDK2Code can scan your workspace and detect existing build output folders automatically — you don't need to point the extension at them manually.

+
    +
  • EDK2: Discover build folders scans the workspace.
  • +
  • EDK2: Use discovered build folders loads the detected folders as workspace configurations.
  • +
  • The Workspace welcome view exposes both actions when nothing is loaded yet.
  • +
+

Discover build folders

+

Compile EDK2 file

+

You can compile an individual EDK2 C file directly from the editor without running a full EDK2 build:

+
    +
  • A play ($(play)) icon is shown in the editor title bar on supported source files.
  • +
  • The command EDK2: Compile Edk2 file invokes the compiler for the active .c file using the flags and include paths recorded in compile_commands.json.
  • +
+

Compile EDK2 file

+
+

⚠ NOTE This compiles the single C file in isolation — it runs outside the regular EDK2 build system and does not link or produce a final binary. It is intended as a fast feedback loop to catch syntax and type errors in a single translation unit without waiting for a full platform build.

+

⚠ REQUIREMENT This feature requires a compile_commands.json to be present in your workspace. This file is generated automatically when you enable compile information during your EDK2 build using the -Y COMPILE_INFO flag.

+
+

Goto overwriting definition

+

When a symbol is overwritten in a DSC (libraries, PCDs, modules), a new code action lets you jump to the overwriting definition instead of the original.

+

Goto overwriting definition

+

MCP server

+

EDK2Code can expose a Model Context Protocol (MCP) SSE server so AI agents and tools (such as GitHub Copilot or other MCP-compatible clients) can query your parsed EDK2 workspace directly.

+

MCP server

+

Starting and stopping

+

Open the Workspace configuration (UI) panel (EDK2: Workspace configuration (UI)) and use the Start MCP Server / Stop MCP Server button in the MCP section, or run the commands from the palette:

+
> EDK2: Start MCP SSE Server
+> EDK2: Stop MCP SSE Server
+
+

The edk2code.mcpServerPort setting controls the listening port (default 3100).

+

Auto-configure workspace MCP

+

To let VS Code and GitHub Copilot discover the server automatically, click Auto-configure workspace MCP in the Settings UI. This writes (or updates) the edk2code server entry in your workspace's .vscode/mcp.json file:

+
{
+    "servers": {
+        "edk2code": {
+            "type": "sse",
+            "url": "http://localhost:3100/sse"
+        }
+    }
+}
+
+

Once this file exists, VS Code will list the edk2code server under MCP Servers in Copilot Chat and any other MCP-compatible client. See the VS Code MCP documentation for more details on how MCP servers work.

+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + Next » + + +
+ + + + + + + + + + + + + + diff --git a/documentation/index.html b/documentation/index.html new file mode 100755 index 0000000..9370cb2 --- /dev/null +++ b/documentation/index.html @@ -0,0 +1,153 @@ + + + + + + + + Index database - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Index database

+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + Next » + + +
+ + + + + + + + + + + + + + diff --git a/img/favicon.ico b/img/favicon.ico new file mode 100755 index 0000000..e85006a Binary files /dev/null and b/img/favicon.ico differ diff --git a/index.html b/index.html new file mode 100755 index 0000000..0824d62 --- /dev/null +++ b/index.html @@ -0,0 +1,162 @@ + + + + + + + + Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ +

EDK2Code

+

Star

+

The EDK2Code Extension for Visual Studio Code enhances the development experience for engineers working with the EDK2 (UEFI) codebase by providing features such as syntax highlighting, code navigation, and error detection. This extension integrates these capabilities directly into Visual Studio Code, enabling developers to streamline their workflow and increase productivity.

+

By leveraging the EDK2Code extension, developers can easily navigate through code, quickly identify errors, and benefit from improved readability of EDK2 source files. This results in a more efficient development process and a smoother coding experience.

+

Additionally, the extension supports various EDK2-specific commands accessible via the command palette, such as rebuilding the index database and configuring the workspace. This comprehensive toolset empowers developers to work more effectively with EDK2 projects, ultimately leading to higher quality code and faster development cycles.

+

Check YouTube video presentation on UEFIForum Channel

+

YouTube presentation

+

Github +VSCODE

+ +
+
+ +
+
+ +
+ +
+ +
+ + + + + Next » + + +
+ + + + + + + + + + + + + + + + diff --git a/js/html5shiv.min.js b/js/html5shiv.min.js new file mode 100755 index 0000000..1a01c94 --- /dev/null +++ b/js/html5shiv.min.js @@ -0,0 +1,4 @@ +/** +* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); diff --git a/js/jquery-3.6.0.min.js b/js/jquery-3.6.0.min.js new file mode 100755 index 0000000..c4c6022 --- /dev/null +++ b/js/jquery-3.6.0.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each((function(){var t=n(this);expand=n(''),expand.on("click",(function(n){return e.toggleCurrent(t),n.stopPropagation(),!1})),t.prepend(expand)}))},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),t=e.find('[href="'+n+'"]');if(0===t.length){var i=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(t=e.find('[href="#'+i.attr("id")+'"]')).length&&(t=e.find('[href="#"]'))}if(t.length>0){$(".wy-menu-vertical .current").removeClass("current").attr("aria-expanded","false"),t.addClass("current").attr("aria-expanded","true"),t.closest("li.toctree-l1").parent().addClass("current").attr("aria-expanded","true");for(let n=1;n<=10;n++)t.closest("li.toctree-l"+n).addClass("current").attr("aria-expanded","true");t[0].scrollIntoView()}}catch(n){console.log("Error expanding nav for anchor",n)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,t=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(t),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",(function(){this.linkScroll=!1}))},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current").attr("aria-expanded","false"),e.siblings().find("li.current").removeClass("current").attr("aria-expanded","false");var t=e.find("> ul li");t.length&&(t.removeClass("current").attr("aria-expanded","false"),e.toggleClass("current").attr("aria-expanded",(function(n,e){return"true"==e?"false":"true"})))}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:n.exports.ThemeNav,StickyNav:n.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],t=0;t` \n\t", - "folding": { - "markers": { - "start": "^\\s*//\\s*#?region\\b", - "end": "^\\s*//\\s*#?endregion\\b" - } - }, - "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", - "indentationRules": { - "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", - "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$" - } -} diff --git a/languages/conf/edk2_common.conf.json b/languages/conf/edk2_common.conf.json deleted file mode 100644 index ab9ed77..0000000 --- a/languages/conf/edk2_common.conf.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "comments": { - "lineComment": "#" - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["!ifdef","!endif"], - ["!ifndef","!endif"], - ["!if","!endif"], - ["<",">"] - - ], - - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - "autoCloseBefore": ";:.,=}])>` \n\t", - "folding": { - "markers": { - "start": "^\\s*//\\s*#?region\\b", - "end": "^\\s*//\\s*#?endregion\\b" - } - }, - "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", - "indentationRules": { - "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", - "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$" - } -} \ No newline at end of file diff --git a/languages/conf/edk2_dec.conf.json b/languages/conf/edk2_dec.conf.json deleted file mode 100644 index 1b7cf3b..0000000 --- a/languages/conf/edk2_dec.conf.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "comments": { - "lineComment": "#" - } -} \ No newline at end of file diff --git a/languages/conf/edk2_dsc.conf.json b/languages/conf/edk2_dsc.conf.json deleted file mode 100644 index 74374f3..0000000 --- a/languages/conf/edk2_dsc.conf.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "comments": { - "lineComment": "#" - } -} \ No newline at end of file diff --git a/languages/conf/edk2_fdf.conf.json b/languages/conf/edk2_fdf.conf.json deleted file mode 100644 index 1b7cf3b..0000000 --- a/languages/conf/edk2_fdf.conf.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "comments": { - "lineComment": "#" - } -} \ No newline at end of file diff --git a/languages/conf/edk2_inf.conf.json b/languages/conf/edk2_inf.conf.json deleted file mode 100644 index 74374f3..0000000 --- a/languages/conf/edk2_inf.conf.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "comments": { - "lineComment": "#" - } -} \ No newline at end of file diff --git a/languages/conf/edk2_uni.conf.json b/languages/conf/edk2_uni.conf.json deleted file mode 100644 index a12cd6b..0000000 --- a/languages/conf/edk2_uni.conf.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/" ] - } -} \ No newline at end of file diff --git a/languages/conf/edk2_vfr.conf.json b/languages/conf/edk2_vfr.conf.json deleted file mode 100644 index 3877871..0000000 --- a/languages/conf/edk2_vfr.conf.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": [ "/*", "*/" ] - }, - "brackets": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["formset", "endformset"], - ["numeric","endnumeric"], - ["oneof","endoneof"], - ["suppressif", "endif"], - ["checkbox", "endcheckbox"], - ["form","endform"], - ["grayoutif","endif"], - ["warningif","endif"], - ["inconsistentif","endif"], - ["disableif","endif"], - ["nosubmitif","endif"], - ["#ifdef","#endif"], - ["#ifndef","#endif"], - ["#if","#endif"] - ], - - "autoClosingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - - "surroundingPairs": [ - ["{", "}"], - ["[", "]"], - ["(", ")"], - ["\"", "\""], - ["'", "'"] - ], - "autoCloseBefore": ";:.,=}])>` \n\t", - "folding": { - "markers": { - "start": "^\\s*//\\s*#?region\\b", - "end": "^\\s*//\\s*#?endregion\\b" - } - }, - "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)", - "indentationRules": { - "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$", - "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$" - } -} diff --git a/languages/syntaxes/asl.tmLanguage.json b/languages/syntaxes/asl.tmLanguage.json deleted file mode 100644 index d267724..0000000 --- a/languages/syntaxes/asl.tmLanguage.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "ASL", - "patterns": [ - { - "include": "#comments" - }, - { - "include": "#constants" - }, - { - "include": "#entities" - }, - { - "include": "#keywords" - }, - { - "include": "#metas" - }, - { - "include": "#strings" - }, - { - "include": "#supports" - }, - { - "include": "#variables" - }, - { - "include": "#invalid" - } - ], - "repository": { - "comments": { - "patterns": [ - { - "begin": "//", - "end": "\\n", - "name": "comment.line.double-slash.asl" - }, - { - "begin": "/\\*", - "end": "\\*/", - "name": "comment.block.asl" - } - ] - }, - "constants": { - "patterns": [ - { - "match": "\\\\.", - "name": "constant.character.escape.asl" - }, - { - "match": "\\b(AccessAs|Acquire|Add|Alias|And|Arg[0-9]|BankField|Break|BreakPoint|Buffer|Case|Concatenate|ConcatenateResTemplate|CondRefOf|Connection|Continue|CopyObject|CreateBitField|CreateByteField|CreateDWordField|CreateField|CreateQWordField|CreateWordField|DataTableRegion|Debug|Decrement|Default|DefinitionBlock|DerefOf|Device|Divide|DMA|DWordIO|DWordMemory|DWordSpace|EISAID|Else|ElseIf|EndDependentFn|Event|ExtendedIO|ExtendedMemory|ExtendedSpace|External|Fatal|Field|FindSetLeftBit|FindSetRightBit|FixedDMA|FixedIO|Fprintf|FromBCD|Function|GpioInt|GpioIo|I2CSerialBusV2|If|Include|Increment|Index|IndexField|Interrupt|IO|IRQ|IRQNoFlags|LAnd|LEqual|LGreater|LGreaterEqual|LLess|LLessEqual|LNot|LNotEqual|Load|LoadTable|Local[0-9]|LOr|Match|Memory24|Memory32|Memory32Fixed|Method|Mid|Mod|Multiply|Mutex|Name|NAnd|NoOp|NOr|Not|Notify|ObjectType|Offset|OperationRegion|Or|Package|PowerResource|Printf|Processor|QWordIO|QWordMemory|QWordSpace|RawDataBuffer|RefOf|Register|Release|Reset|ResourceTemplate|Return|Scope|ShiftLeft|ShiftRight|Signal|SizeOf|Sleep|SPISerialbusV2|Stall|StartDependentFn|StartDependentFnNoPri|Store|Subtract|Switch|ThermalZone|Timer|ToBCD|ToBuffer|ToDecimalString|ToHexString|ToInteger|ToPLD|ToString|ToUUID|Unicode|Unload|UARTSerialBusV2|VendorLong|VendorShort|Wait|While|WordBusNumber|WordIO|WordSpace|Xor)\\b", - "name": "constant.language.asl" - }, - { - "match": "\\b((0(x|X)[0-9a-fA-F]+)|(0[0-7]+)|[0-9]|One|Ones|Zero)\\b", - "name": "constant.numeric.asl" - } - ] - }, - "entity": { - "patterns": [ - ] - }, - "keywords": { - "patterns": [ - { - "match": "\\b(AttribQuick|AttribSendReceive|AttribByte|AttribBytes|AttribRawBytes|AttribRawProcessBytes|AttribWord|AttribBlock|AttribProcessCall|AttribBlockProcessCall|AnyAcc|ByteAcc|WordAcc|DWordAcc|QWordAcc|BufferAcc|AddressRangeMemory|AddressRangeReserved|AddressRangeNVS|AddressRangeACPI|RegionSpaceKeyword|FFixedHW|PCC|AddressingMode7Bit|AddressingMode10Bit|DataBitsFive|DataBitsSix|DataBitsSeven|DataBitsEight|DataBitsNine|BusMaster|NotBusMaster|ClockPhaseFirst|ClockPhaseSecond|ClockPolarityLow|ClockPolarityHigh|SubDecode|PosDecode|BigEndianing|LittleEndian|FlowControlNone|FlowControlXon|FlowControlHardware|Edge|Level|ActiveHigh|ActiveLow|ActiveBoth|Decode16|Decode10|IoRestrictionNone|IoRestrictionInputOnly|IoRestrictionOutputOnly|IoRestrictionNoneAndPreserve|Lock|NoLock|MTR|MEQ|MLE|MLT|MGE|MGT|MaxFixed|MaxNotFixed|Cacheable|WriteCombining|Prefetchable|NonCacheable|MinFixed|MinNotFixed|UnknownObj|IntObj|StrObj|BuffObj|PkgObj|FieldUnitObj|DeviceObj|EventObj|MethodObj|MutexObj|OpRegionObj|PowerResObj|ProcessorObj|ThermalZoneObj|BuffFieldObj|DDBHandleObj|ParityTypeNone|ParityTypeSpace|ParityTypeMark|ParityTypeOdd|ParityTypeEven|PullDefault|PullUp|PullDown|PullNone|PolarityHigh|PolarityLow|ISAOnlyRanges|NonISAOnlyRanges|EntireRange|ReadWrite|ReadOnly|UserDefRegionSpace|SystemIO|SystemMemory|PCI_Config|EmbeddedControl|SMBus|SystemCMOS|PciBarTarget|IPMI|GeneralPurposeIO|GenericSerialBus|ResourceConsumer|ResourceProducer|Serialized|NotSerialized|Shared|Exclusive|SharedAndWake|ExclusiveAndWake|ControllerInitiated|DeviceInitiated|StopBitsZero|StopBitsOne|StopBitsOnePlusHalf|StopBitsTwo|Width8Bit|Width16Bit|Width32Bit|Width64Bit|Width128Bit|Width256Bit|SparseTranslation|DenseTranslation|TypeTranslation|TypeStatic|Preserve|WriteAsOnes|WriteAsZeros|Transfer8|Transfer16|Transfer8_16|ThreeWireMode|FourWireMode)\\b", - "name": "keyword.other.asl" - }, - { - "match": "\\b(s*(include|define|undef))\\b", - "name": "keyword.control.asl" - } - ] - }, - "metas": { - "patterns": [ - { - "match": "\\[|\\]|\\(|\\)|\\{|\\}", - "name": "meta.brackets.asl" - } - ] - }, - "strings": { - "patterns": [ - { - "begin": "\"", - "end": "\"", - "name": "string.quoted.double.asl" - }, - { - "match": "\\+|/|%|\\*|-|<<|>>|&|\\||\\^|~|\\+\\+|--", - "name": "punctuation.math.asl" - }, - { - "match": "==|!=|<|>|<=|>=|&&|\\|\\||!", - "name": "punctuation.logical.asl" - }, - { - "match": "=|\\+=|/=|%=|\\*=|-=|<<=|>>=|&=|\\|=|\\^=", - "name": "punctuation.assign.asl" - } - ] - }, - "supports": { - "patterns": [ - ] - }, - "variables": { - "patterns": [ - { - "match": "\\b(_AC[0-9]|_ADR|_AEI|_ALC|_ALI|_ALN|_ALP|_ALR|_ALT|_ART|_ASI|_ASZ|_ATT|_BAS|_BBN|_BCL|_BCM|_BCT|_BDN|_BIF|_BI[0-9]|_BLT|_BM|_BMA|_BMC|_BMD|_BMS|_BQC|_BST|_BTH|_BTM|_BTP|_CBA|_CDM|_CID|_CLS|_CPC|_CRS|_CRT|_CSD|_CST|_CWS|_DBT|_DCK|_DCS|_DDC|_DDN|_DEC|_DEP|_DGS|_DIS|_DLM|_DMA|_DOS|_DPL|_DRS|_DSD|_DSM|_DSS|_DSW|_DTI|_E[0-9][0-9]|_EC|_EDL|_EJD|_EJ[0-9]|_END|_EVT|_FDE|_FDI|_FDM|_FIF|_FIT|_FI[0-9]|_FLC|_FPS|_FSL|_GAI|_GCP|_GHL|_GL|_GLK|_GPD|_GPE|_GRA|_GRT|_GSB|_GTF|_GTM|_GWS|_HE|_HID|_HOT|_HPP|_HP[0-9]|_HRV|_IFT|_INI|_IOR|_IRC|_L[0-9][0-9]|_LCK|_LEN|_LID|_LIN|_LL|_LPI|_MAF|_MAT|_MA[0-9]|_MBM|_MEM|_MIF|_MIN|_MLS|_MOD|_MSG|_MSM|_MTL|_MTP|_NTT|_OFF|_ON|_OS|_OSI|_OST|_PAI|_PAR|_PCL|_PCT|_PDC|_PDL|_PHA|_PIC|_PIF|_PIN|_PLD|_PMC|_PMD|_PMM|_POL|_PPC|_PPE|_PPI|_PR|_PR0|_PR2|_PR3|_PRE|_PRL|_PRR|_PRS|_PRT|_PRW|_PS0|_PS1|_PS2|_PS3|_PSC|_PSD|_PSE|_PSL|_PSR|_PSS|_PSV|_PSW|_PTC|_PTP|_PTS|_PUR|_P[0-9]M|_RBO|_RBW|_RDI|_REG|_REV|_RMV|_RNG|_ROM|_RST|_RT|_RTV|_RW|_R[0-9]L|_S0|_S1|_S2|_S3|_S4|_S5|_S1D|_S2D|_S3D|_S4D|_S1W|_S2W|_S3W|_S4W|_SB|_SBS|_SCP|_SDD|_SEG|_SHL|_SHR|_SI|_SIZ|_SLI|_SLV|_SPD|_SPE|_SRS|_SRT|_SRV|_STA|_STB|_STM|_STR|_STV|_SUB|_SUN|_SWS|_T_[0-9]|_TC1|_TC2|_TDL|_TFP|_TIP|_TIV|_TMP|_TPC|_TPT|_TRA|_TRS|_TRT|_TSD|_TSF|_TSN|_TSP|_TSS|_TTP|_TTS|_T[0-9]L|_TYP|_TZ|_TZD|_TZM|_TZP|_UID|_UPC|_UPD|_UPP|_VEN|_VPO|_WAK|_W[0-9][0-9])\\b", - "name": "variable.language.asl" - } - ] - }, - "invalid": { - "patterns": [ - ] - } - }, - "scopeName": "source.asl", - "uuid": "FEA01457-E381-4135-9475-C6AFD0076C61" -} \ No newline at end of file diff --git a/languages/syntaxes/edk2_dec.tmLanguage.json b/languages/syntaxes/edk2_dec.tmLanguage.json deleted file mode 100644 index 5bba909..0000000 --- a/languages/syntaxes/edk2_dec.tmLanguage.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "source.edk2_dec", - "patterns": [ - { - "include": "#edk2_dec_color" - } - ], - "repository": { - "edk2_dec_color": { - "patterns": [ - { - "name": "variable.language.edk2_dec", - "match": "((?)" - }, - { - "name": "support.function.edk2_dec", - "match": "(?<=\\$\\()[a-zA-Z0-9_]+(?=\\))" - }, - { - "name": "comment.line.number-sign.edk2_dec", - "begin": "#", - "end": "\n" - } - ] - } - }, - "scopeName": "source.edk2_dec" -} \ No newline at end of file diff --git a/languages/syntaxes/edk2_dsc.tmLanguage.json b/languages/syntaxes/edk2_dsc.tmLanguage.json deleted file mode 100644 index c765874..0000000 --- a/languages/syntaxes/edk2_dsc.tmLanguage.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "source.edk2_dsc", - "patterns": [ - { - "include": "#edk2_dsc_color" - } - ], - "repository": { - "edk2_dsc_color": { - "patterns": [ - { - "name": "string.quoted.edk2_dsc", - "match": "(?:\\w[\\w\\d\\[\\]]+\\.)+[\\w\\d\\[\\]]+" - }, - { - "name": "variable.language.edk2_dsc", - "match": "\\$\\(.*?\\)" - }, - { - "name": "variable.language.edk2_dsc", - "match": "((?)" - }, - { - "name": "support.function.edk2_dsc", - "match": "(?<=\\$\\()[a-zA-Z0-9_]+(?=\\))" - }, - { - "name": "comment.line.number-sign.edk2_dsc", - "begin": "#", - "end": "\n" - } - ] - } - }, - "scopeName": "source.edk2_dsc" -} \ No newline at end of file diff --git a/languages/syntaxes/edk2_fdf.tmLanguage.json b/languages/syntaxes/edk2_fdf.tmLanguage.json deleted file mode 100644 index 520c0ae..0000000 --- a/languages/syntaxes/edk2_fdf.tmLanguage.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "source.edk2_fdf", - "patterns": [ - { - "include": "#edk2_fdf_color" - } - ], - "repository": { - "edk2_fdf_color": { - "patterns": [ - { - "//": "TO-DO: Too much specific keywords in FDF, should revisit for finding better way of color syntax." - }, - { - "name": "variable.language.edk2_dsc", - "match": "\\$\\(.*?\\)" - }, - { - "name": "variable.language.edk2_fdf", - "match": "((?)" - }, - { - "name": "support.function.edk2_fdf", - "match": "(?<=\\$\\()[a-zA-Z0-9_]+(?=\\))" - }, - { - "name": "comment.line.number-sign.edk2_fdf", - "begin": "#|\/\/", - "end": "\n" - } - ] - } - }, - "scopeName": "source.edk2_fdf" -} \ No newline at end of file diff --git a/languages/syntaxes/edk2_inf.tmLanguage.json b/languages/syntaxes/edk2_inf.tmLanguage.json deleted file mode 100644 index ff6a492..0000000 --- a/languages/syntaxes/edk2_inf.tmLanguage.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "source.edk2_inf", - "patterns": [ - { - "include": "#edk2_inf_color" - } - ], - "repository": { - "edk2_inf_color": { - "patterns": [ - { - "name": "variable.language.edk2_inf", - "match": "((?)" - }, - { - "name": "support.function.edk2_inf", - "match": "(?<=\\$\\()[a-zA-Z0-9_]+(?=\\))" - }, - { - "name": "comment.line.number-sign.edk2_inf", - "begin": "#", - "end": "\n" - } - ] - } - }, - "scopeName": "source.edk2_inf" -} \ No newline at end of file diff --git a/languages/syntaxes/edk2_uni.tmLanguage.json b/languages/syntaxes/edk2_uni.tmLanguage.json deleted file mode 100644 index 94fa58b..0000000 --- a/languages/syntaxes/edk2_uni.tmLanguage.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "source.edk2_uni", - "patterns": [ - { - "include": "#edk2_uni_color" - }, - { - "include": "source.c" - } - ], - "repository": { - "edk2_uni_color": { - "patterns": [ - { - "name": "variable.language.edk2_uni", - "match": "(?<=\\#)(string|language|langdef|fontdef|font)" - } - ] - } - }, - "scopeName": "source.edk2_uni" -} \ No newline at end of file diff --git a/languages/syntaxes/edk2_vfr.tmLanguage.json b/languages/syntaxes/edk2_vfr.tmLanguage.json deleted file mode 100644 index 40eb085..0000000 --- a/languages/syntaxes/edk2_vfr.tmLanguage.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", - "name": "source.edk2_vfr", - "patterns": [ - { - "include": "#edk2_vfr_color" - }, - { - "include": "source.c" - } - ], - "repository": { - "edk2_vfr_color": { - "patterns": [ - { - "name": "variable.language.edk2_vfr", - "match": "((? + + + + + + + 1.0.9 - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

Thanks for using the Edk2Code Vscode extension.

+

🎉 If you find this extension useful 🎉:

+ +

1.0.9

+

DSC analysis

+

Shows problems in DSC files

+

alt text

+

Module map

+

Added context menu action Show Module Map. This action is available on INF files and will open EDK2 module map side panel to show: +- Library tree +- Source files tree (including Header files) +alt text

+

You can also copy the path of the element selected in EDK2 module map using mouse context menu.

+

alt text

+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + Next » + + +
+ + + + + + + + + + + + + + diff --git a/releases/1.0.9/moduleMap.png b/releases/1.0.9/moduleMap.png new file mode 100755 index 0000000..169b1f4 Binary files /dev/null and b/releases/1.0.9/moduleMap.png differ diff --git a/releases/2.0.0/index.html b/releases/2.0.0/index.html new file mode 100755 index 0000000..fcd884d --- /dev/null +++ b/releases/2.0.0/index.html @@ -0,0 +1,265 @@ + + + + + + + + 2.0.0 - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + + +
  • +
  • +
+
+
+
+
+ +

2.0.0

+

Edk2Code sidebar

+

The extension now lives in a dedicated activity bar container. All Edk2Code views (Workspace, Module Info) are grouped together in the sidebar instead of being attached to the Explorer view.

+

Edk2Code sidebar activity bar entry

+
+

Workspace view

+

The new Workspace view is a single, persistent tree representation of your parsed EDK2 workspace. It replaces the previous Module Map, Reference Tree and Library Tree commands.

+

Workspace view

+

Key capabilities:

+
    +
  • Sub-trees and includes — DSC, INF, FDF and source files are organized hierarchically. Header includes and library sub-trees are integrated into the tree.
  • +
  • +

    Search — Click the $(search) action in the view title bar to find any node in the workspace tree.

    +

    Workspace search

    +
  • +
  • +

    Filter inactive elements — Toggle the $(filter) action to hide grayed-out (inactive) items.

    +

    Filter inactive

    +
  • +
  • +

    Reveal active editor — The $(target) action jumps from the currently open file to its location in the workspace tree.

    +

    Reveal in workspace tree

    +
  • +
  • +

    Drag and drop — Reorganize nodes in the workspace tree directly with the mouse.

    +

    Drag and drop

    +
  • +
  • +

    Multiple workspaces — When multiple build configurations are loaded, switch between them from the $(repo) action in the title bar. Searching for symbols automatically switches to the workspace that owns the result.

    +

    Select workspace

    +
  • +
  • +

    Copy node path / Copy tree — Quickly copy the path of a node, or export the entire tree as text via the $(copy) action.

    +
  • +
  • +

    Welcome view — When no workspace is loaded, the view guides you through discovering build folders or opening the configuration UI.

    +

    Welcome view

    +
  • +
+
+

Module Info view

+

The new Module Info view shows the EDK2 module information for the file you are currently editing. As soon as you open a C, INF or related source file that belongs to a module, the view populates with:

+
    +
  • The owning INF and its DSC declaration
  • +
  • Libraries linked to the module
  • +
  • Quick navigation actions (go to definition, open file, go to DSC declaration)
  • +
+

Double-click any entry to jump directly to the corresponding source location.

+

Module Info view

+
+

Build folder auto-discovery

+

EDK2Code can now scan your workspace and automatically detect existing build output folders, so you don't have to point the extension at them manually.

+
    +
  • Run EDK2: Discover build folders to scan the workspace.
  • +
  • Once discovered, run EDK2: Use discovered build folders to load them directly.
  • +
  • The Workspace view welcome page surfaces these actions when nothing is loaded yet.
  • +
+

Build folder discovery

+
+

Compile EDK2 file

+

You can now compile an individual EDK2 file (e.g. a .c belonging to a module) directly from the editor.

+
    +
  • A play ($(play)) icon is shown in the editor title bar on supported source files.
  • +
  • The command EDK2: Compile Edk2 file invokes the build for the parent module of the active file.
  • +
+

Compile EDK2 file button

+
+

MCP server integration

+

EDK2Code now exposes an MCP (Model Context Protocol) SSE server that lets AI agents and external tools query your parsed EDK2 workspace.

+
    +
  • Start with EDK2: Start MCP SSE Server and stop with EDK2: Stop MCP SSE Server.
  • +
  • Configure the listening port via the edk2code.mcpServerPort setting (default 3100).
  • +
+

MCP server

+
+

Settings UI

+

A redesigned graphical Workspace configuration (UI) panel makes managing build configurations easier — no more hand-editing JSON for common setups.

+
    +
  • Launch from the Workspace view title bar ($(gear) icon) or via the EDK2: Workspace configuration (UI) command.
  • +
+

Settings UI

+
+

Goto overwriting definition

+

When a symbol is overwritten in a DSC (libraries, PCDs, modules), a new code action lets you jump directly to the overwriting definition.

+

Goto overwriting definition

+
+

Other improvements

+
    +
  • Disable cscope — A new edk2code.useCscope setting lets you turn off cscope integration entirely. When disabled, the cscope database is not built or queried (call hierarchy and cscope-based go-to-definition become unavailable).
  • +
  • Unload workspace — New EDK2: Unload workspace command to clear the currently loaded build configuration.
  • +
  • Refresh workspace config — Reload the workspace configuration without restarting VS Code.
  • +
  • Focus INF from C files — Improved navigation from C source files back to their owning INF module.
  • +
  • Better module symbols — DSC parser now recognizes module sub-context sections, build options, and provides improved symbols for libraries and modules.
  • +
  • Loading and discovery indicators — Progress indicators are shown while the workspace is being parsed or build folders are being discovered.
  • +
  • Improved grayout controller — Inactive code regions are computed and updated more reliably.
  • +
  • Path improvements — Missing paths now report folders instead of file names, and tooltips include the full path.
  • +
  • Extensive test suite — New parser and workspace tests covering ASL, DEC, DSC, FDF, INF and VFR.
  • +
+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + +
+ + + + + + + + + + + + + + diff --git a/requirements/index.html b/requirements/index.html new file mode 100755 index 0000000..4ea0ab0 --- /dev/null +++ b/requirements/index.html @@ -0,0 +1,162 @@ + + + + + + + + Requirements - Edk2Code Vscode Extension + + + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • + +
  • +
  • +
+
+
+
+
+ +

Requirements

+

Visual Studio Code ^1.77.0

+

Cscope

+

Cscope is used for some C related functionality of the extension. On windows systems the cscope comes already included in the extension.

+

For linux systems you need to install cscope manually.

+

Ubuntu installation example: sudo apt install cscope

+

Additionally, you can use the vscode setting edk2code.cscopeOverwritePath to point cscope to your preferred installation path.

+ +
+
+ +
+
+ +
+ +
+ +
+ + + + « Previous + + + Next » + + +
+ + + + + + + + + + + + + + diff --git a/scripts/create_draft_release.js b/scripts/create_draft_release.js deleted file mode 100644 index f58ac75..0000000 --- a/scripts/create_draft_release.js +++ /dev/null @@ -1,24 +0,0 @@ -const { execSync } = require('child_process'); -const fs = require('fs'); - -// Check if gh CLI is installed -try { - execSync('gh --version', { stdio: 'ignore' }); -} catch (error) { - console.error('gh CLI is not installed. Please install it first.'); - process.exit(1); -} - -// Parse the version from package.json -const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8')); -const version = packageJson.version; - -// Get the latest commit hash -const latestCommit = execSync('git rev-parse HEAD').toString().trim(); - -// Create a new draft release with the version name -execSync(`gh release create v${version} -t "v${version}" -n "Draft release for commit ${latestCommit}" --draft`, { stdio: 'inherit' }); - -// Print the URL to open the release page in the browser -const repoUrl = execSync('gh repo view --json url --jq ".url"').toString().trim(); -console.log(`Release created. You can view it at: ${repoUrl}/releases/tag/v${version}`); diff --git a/search.html b/search.html new file mode 100755 index 0000000..09c0710 --- /dev/null +++ b/search.html @@ -0,0 +1,145 @@ + + + + + + + + Edk2Code Vscode Extension + + + + + + + + + + + + + +
+ + +
+ +
+
+
    +
  • +
  • +
  • +
+
+
+
+
+ + +

Search Results

+ + + +
+ Searching... +
+ + +
+
+ +
+
+ +
+ +
+ +
+ + + + + +
+ + + + + + + + + + + + + + diff --git a/search/lunr.js b/search/lunr.js new file mode 100755 index 0000000..aca0a16 --- /dev/null +++ b/search/lunr.js @@ -0,0 +1,3475 @@ +/** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + */ + +;(function(){ + +/** + * A convenience function for configuring and constructing + * a new lunr Index. + * + * A lunr.Builder instance is created and the pipeline setup + * with a trimmer, stop word filter and stemmer. + * + * This builder object is yielded to the configuration function + * that is passed as a parameter, allowing the list of fields + * and other builder parameters to be customised. + * + * All documents _must_ be added within the passed config function. + * + * @example + * var idx = lunr(function () { + * this.field('title') + * this.field('body') + * this.ref('id') + * + * documents.forEach(function (doc) { + * this.add(doc) + * }, this) + * }) + * + * @see {@link lunr.Builder} + * @see {@link lunr.Pipeline} + * @see {@link lunr.trimmer} + * @see {@link lunr.stopWordFilter} + * @see {@link lunr.stemmer} + * @namespace {function} lunr + */ +var lunr = function (config) { + var builder = new lunr.Builder + + builder.pipeline.add( + lunr.trimmer, + lunr.stopWordFilter, + lunr.stemmer + ) + + builder.searchPipeline.add( + lunr.stemmer + ) + + config.call(builder, builder) + return builder.build() +} + +lunr.version = "2.3.9" +/*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * A namespace containing utils for the rest of the lunr library + * @namespace lunr.utils + */ +lunr.utils = {} + +/** + * Print a warning message to the console. + * + * @param {String} message The message to be printed. + * @memberOf lunr.utils + * @function + */ +lunr.utils.warn = (function (global) { + /* eslint-disable no-console */ + return function (message) { + if (global.console && console.warn) { + console.warn(message) + } + } + /* eslint-enable no-console */ +})(this) + +/** + * Convert an object to a string. + * + * In the case of `null` and `undefined` the function returns + * the empty string, in all other cases the result of calling + * `toString` on the passed object is returned. + * + * @param {Any} obj The object to convert to a string. + * @return {String} string representation of the passed object. + * @memberOf lunr.utils + */ +lunr.utils.asString = function (obj) { + if (obj === void 0 || obj === null) { + return "" + } else { + return obj.toString() + } +} + +/** + * Clones an object. + * + * Will create a copy of an existing object such that any mutations + * on the copy cannot affect the original. + * + * Only shallow objects are supported, passing a nested object to this + * function will cause a TypeError. + * + * Objects with primitives, and arrays of primitives are supported. + * + * @param {Object} obj The object to clone. + * @return {Object} a clone of the passed object. + * @throws {TypeError} when a nested object is passed. + * @memberOf Utils + */ +lunr.utils.clone = function (obj) { + if (obj === null || obj === undefined) { + return obj + } + + var clone = Object.create(null), + keys = Object.keys(obj) + + for (var i = 0; i < keys.length; i++) { + var key = keys[i], + val = obj[key] + + if (Array.isArray(val)) { + clone[key] = val.slice() + continue + } + + if (typeof val === 'string' || + typeof val === 'number' || + typeof val === 'boolean') { + clone[key] = val + continue + } + + throw new TypeError("clone is not deep and does not support nested objects") + } + + return clone +} +lunr.FieldRef = function (docRef, fieldName, stringValue) { + this.docRef = docRef + this.fieldName = fieldName + this._stringValue = stringValue +} + +lunr.FieldRef.joiner = "/" + +lunr.FieldRef.fromString = function (s) { + var n = s.indexOf(lunr.FieldRef.joiner) + + if (n === -1) { + throw "malformed field ref string" + } + + var fieldRef = s.slice(0, n), + docRef = s.slice(n + 1) + + return new lunr.FieldRef (docRef, fieldRef, s) +} + +lunr.FieldRef.prototype.toString = function () { + if (this._stringValue == undefined) { + this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef + } + + return this._stringValue +} +/*! + * lunr.Set + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * A lunr set. + * + * @constructor + */ +lunr.Set = function (elements) { + this.elements = Object.create(null) + + if (elements) { + this.length = elements.length + + for (var i = 0; i < this.length; i++) { + this.elements[elements[i]] = true + } + } else { + this.length = 0 + } +} + +/** + * A complete set that contains all elements. + * + * @static + * @readonly + * @type {lunr.Set} + */ +lunr.Set.complete = { + intersect: function (other) { + return other + }, + + union: function () { + return this + }, + + contains: function () { + return true + } +} + +/** + * An empty set that contains no elements. + * + * @static + * @readonly + * @type {lunr.Set} + */ +lunr.Set.empty = { + intersect: function () { + return this + }, + + union: function (other) { + return other + }, + + contains: function () { + return false + } +} + +/** + * Returns true if this set contains the specified object. + * + * @param {object} object - Object whose presence in this set is to be tested. + * @returns {boolean} - True if this set contains the specified object. + */ +lunr.Set.prototype.contains = function (object) { + return !!this.elements[object] +} + +/** + * Returns a new set containing only the elements that are present in both + * this set and the specified set. + * + * @param {lunr.Set} other - set to intersect with this set. + * @returns {lunr.Set} a new set that is the intersection of this and the specified set. + */ + +lunr.Set.prototype.intersect = function (other) { + var a, b, elements, intersection = [] + + if (other === lunr.Set.complete) { + return this + } + + if (other === lunr.Set.empty) { + return other + } + + if (this.length < other.length) { + a = this + b = other + } else { + a = other + b = this + } + + elements = Object.keys(a.elements) + + for (var i = 0; i < elements.length; i++) { + var element = elements[i] + if (element in b.elements) { + intersection.push(element) + } + } + + return new lunr.Set (intersection) +} + +/** + * Returns a new set combining the elements of this and the specified set. + * + * @param {lunr.Set} other - set to union with this set. + * @return {lunr.Set} a new set that is the union of this and the specified set. + */ + +lunr.Set.prototype.union = function (other) { + if (other === lunr.Set.complete) { + return lunr.Set.complete + } + + if (other === lunr.Set.empty) { + return this + } + + return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements))) +} +/** + * A function to calculate the inverse document frequency for + * a posting. This is shared between the builder and the index + * + * @private + * @param {object} posting - The posting for a given term + * @param {number} documentCount - The total number of documents. + */ +lunr.idf = function (posting, documentCount) { + var documentsWithTerm = 0 + + for (var fieldName in posting) { + if (fieldName == '_index') continue // Ignore the term index, its not a field + documentsWithTerm += Object.keys(posting[fieldName]).length + } + + var x = (documentCount - documentsWithTerm + 0.5) / (documentsWithTerm + 0.5) + + return Math.log(1 + Math.abs(x)) +} + +/** + * A token wraps a string representation of a token + * as it is passed through the text processing pipeline. + * + * @constructor + * @param {string} [str=''] - The string token being wrapped. + * @param {object} [metadata={}] - Metadata associated with this token. + */ +lunr.Token = function (str, metadata) { + this.str = str || "" + this.metadata = metadata || {} +} + +/** + * Returns the token string that is being wrapped by this object. + * + * @returns {string} + */ +lunr.Token.prototype.toString = function () { + return this.str +} + +/** + * A token update function is used when updating or optionally + * when cloning a token. + * + * @callback lunr.Token~updateFunction + * @param {string} str - The string representation of the token. + * @param {Object} metadata - All metadata associated with this token. + */ + +/** + * Applies the given function to the wrapped string token. + * + * @example + * token.update(function (str, metadata) { + * return str.toUpperCase() + * }) + * + * @param {lunr.Token~updateFunction} fn - A function to apply to the token string. + * @returns {lunr.Token} + */ +lunr.Token.prototype.update = function (fn) { + this.str = fn(this.str, this.metadata) + return this +} + +/** + * Creates a clone of this token. Optionally a function can be + * applied to the cloned token. + * + * @param {lunr.Token~updateFunction} [fn] - An optional function to apply to the cloned token. + * @returns {lunr.Token} + */ +lunr.Token.prototype.clone = function (fn) { + fn = fn || function (s) { return s } + return new lunr.Token (fn(this.str, this.metadata), this.metadata) +} +/*! + * lunr.tokenizer + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * A function for splitting a string into tokens ready to be inserted into + * the search index. Uses `lunr.tokenizer.separator` to split strings, change + * the value of this property to change how strings are split into tokens. + * + * This tokenizer will convert its parameter to a string by calling `toString` and + * then will split this string on the character in `lunr.tokenizer.separator`. + * Arrays will have their elements converted to strings and wrapped in a lunr.Token. + * + * Optional metadata can be passed to the tokenizer, this metadata will be cloned and + * added as metadata to every token that is created from the object to be tokenized. + * + * @static + * @param {?(string|object|object[])} obj - The object to convert into tokens + * @param {?object} metadata - Optional metadata to associate with every token + * @returns {lunr.Token[]} + * @see {@link lunr.Pipeline} + */ +lunr.tokenizer = function (obj, metadata) { + if (obj == null || obj == undefined) { + return [] + } + + if (Array.isArray(obj)) { + return obj.map(function (t) { + return new lunr.Token( + lunr.utils.asString(t).toLowerCase(), + lunr.utils.clone(metadata) + ) + }) + } + + var str = obj.toString().toLowerCase(), + len = str.length, + tokens = [] + + for (var sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) { + var char = str.charAt(sliceEnd), + sliceLength = sliceEnd - sliceStart + + if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) { + + if (sliceLength > 0) { + var tokenMetadata = lunr.utils.clone(metadata) || {} + tokenMetadata["position"] = [sliceStart, sliceLength] + tokenMetadata["index"] = tokens.length + + tokens.push( + new lunr.Token ( + str.slice(sliceStart, sliceEnd), + tokenMetadata + ) + ) + } + + sliceStart = sliceEnd + 1 + } + + } + + return tokens +} + +/** + * The separator used to split a string into tokens. Override this property to change the behaviour of + * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens. + * + * @static + * @see lunr.tokenizer + */ +lunr.tokenizer.separator = /[\s\-]+/ +/*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * lunr.Pipelines maintain an ordered list of functions to be applied to all + * tokens in documents entering the search index and queries being ran against + * the index. + * + * An instance of lunr.Index created with the lunr shortcut will contain a + * pipeline with a stop word filter and an English language stemmer. Extra + * functions can be added before or after either of these functions or these + * default functions can be removed. + * + * When run the pipeline will call each function in turn, passing a token, the + * index of that token in the original list of all tokens and finally a list of + * all the original tokens. + * + * The output of functions in the pipeline will be passed to the next function + * in the pipeline. To exclude a token from entering the index the function + * should return undefined, the rest of the pipeline will not be called with + * this token. + * + * For serialisation of pipelines to work, all functions used in an instance of + * a pipeline should be registered with lunr.Pipeline. Registered functions can + * then be loaded. If trying to load a serialised pipeline that uses functions + * that are not registered an error will be thrown. + * + * If not planning on serialising the pipeline then registering pipeline functions + * is not necessary. + * + * @constructor + */ +lunr.Pipeline = function () { + this._stack = [] +} + +lunr.Pipeline.registeredFunctions = Object.create(null) + +/** + * A pipeline function maps lunr.Token to lunr.Token. A lunr.Token contains the token + * string as well as all known metadata. A pipeline function can mutate the token string + * or mutate (or add) metadata for a given token. + * + * A pipeline function can indicate that the passed token should be discarded by returning + * null, undefined or an empty string. This token will not be passed to any downstream pipeline + * functions and will not be added to the index. + * + * Multiple tokens can be returned by returning an array of tokens. Each token will be passed + * to any downstream pipeline functions and all will returned tokens will be added to the index. + * + * Any number of pipeline functions may be chained together using a lunr.Pipeline. + * + * @interface lunr.PipelineFunction + * @param {lunr.Token} token - A token from the document being processed. + * @param {number} i - The index of this token in the complete list of tokens for this document/field. + * @param {lunr.Token[]} tokens - All tokens for this document/field. + * @returns {(?lunr.Token|lunr.Token[])} + */ + +/** + * Register a function with the pipeline. + * + * Functions that are used in the pipeline should be registered if the pipeline + * needs to be serialised, or a serialised pipeline needs to be loaded. + * + * Registering a function does not add it to a pipeline, functions must still be + * added to instances of the pipeline for them to be used when running a pipeline. + * + * @param {lunr.PipelineFunction} fn - The function to check for. + * @param {String} label - The label to register this function with + */ +lunr.Pipeline.registerFunction = function (fn, label) { + if (label in this.registeredFunctions) { + lunr.utils.warn('Overwriting existing registered function: ' + label) + } + + fn.label = label + lunr.Pipeline.registeredFunctions[fn.label] = fn +} + +/** + * Warns if the function is not registered as a Pipeline function. + * + * @param {lunr.PipelineFunction} fn - The function to check for. + * @private + */ +lunr.Pipeline.warnIfFunctionNotRegistered = function (fn) { + var isRegistered = fn.label && (fn.label in this.registeredFunctions) + + if (!isRegistered) { + lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\n', fn) + } +} + +/** + * Loads a previously serialised pipeline. + * + * All functions to be loaded must already be registered with lunr.Pipeline. + * If any function from the serialised data has not been registered then an + * error will be thrown. + * + * @param {Object} serialised - The serialised pipeline to load. + * @returns {lunr.Pipeline} + */ +lunr.Pipeline.load = function (serialised) { + var pipeline = new lunr.Pipeline + + serialised.forEach(function (fnName) { + var fn = lunr.Pipeline.registeredFunctions[fnName] + + if (fn) { + pipeline.add(fn) + } else { + throw new Error('Cannot load unregistered function: ' + fnName) + } + }) + + return pipeline +} + +/** + * Adds new functions to the end of the pipeline. + * + * Logs a warning if the function has not been registered. + * + * @param {lunr.PipelineFunction[]} functions - Any number of functions to add to the pipeline. + */ +lunr.Pipeline.prototype.add = function () { + var fns = Array.prototype.slice.call(arguments) + + fns.forEach(function (fn) { + lunr.Pipeline.warnIfFunctionNotRegistered(fn) + this._stack.push(fn) + }, this) +} + +/** + * Adds a single function after a function that already exists in the + * pipeline. + * + * Logs a warning if the function has not been registered. + * + * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline. + * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline. + */ +lunr.Pipeline.prototype.after = function (existingFn, newFn) { + lunr.Pipeline.warnIfFunctionNotRegistered(newFn) + + var pos = this._stack.indexOf(existingFn) + if (pos == -1) { + throw new Error('Cannot find existingFn') + } + + pos = pos + 1 + this._stack.splice(pos, 0, newFn) +} + +/** + * Adds a single function before a function that already exists in the + * pipeline. + * + * Logs a warning if the function has not been registered. + * + * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline. + * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline. + */ +lunr.Pipeline.prototype.before = function (existingFn, newFn) { + lunr.Pipeline.warnIfFunctionNotRegistered(newFn) + + var pos = this._stack.indexOf(existingFn) + if (pos == -1) { + throw new Error('Cannot find existingFn') + } + + this._stack.splice(pos, 0, newFn) +} + +/** + * Removes a function from the pipeline. + * + * @param {lunr.PipelineFunction} fn The function to remove from the pipeline. + */ +lunr.Pipeline.prototype.remove = function (fn) { + var pos = this._stack.indexOf(fn) + if (pos == -1) { + return + } + + this._stack.splice(pos, 1) +} + +/** + * Runs the current list of functions that make up the pipeline against the + * passed tokens. + * + * @param {Array} tokens The tokens to run through the pipeline. + * @returns {Array} + */ +lunr.Pipeline.prototype.run = function (tokens) { + var stackLength = this._stack.length + + for (var i = 0; i < stackLength; i++) { + var fn = this._stack[i] + var memo = [] + + for (var j = 0; j < tokens.length; j++) { + var result = fn(tokens[j], j, tokens) + + if (result === null || result === void 0 || result === '') continue + + if (Array.isArray(result)) { + for (var k = 0; k < result.length; k++) { + memo.push(result[k]) + } + } else { + memo.push(result) + } + } + + tokens = memo + } + + return tokens +} + +/** + * Convenience method for passing a string through a pipeline and getting + * strings out. This method takes care of wrapping the passed string in a + * token and mapping the resulting tokens back to strings. + * + * @param {string} str - The string to pass through the pipeline. + * @param {?object} metadata - Optional metadata to associate with the token + * passed to the pipeline. + * @returns {string[]} + */ +lunr.Pipeline.prototype.runString = function (str, metadata) { + var token = new lunr.Token (str, metadata) + + return this.run([token]).map(function (t) { + return t.toString() + }) +} + +/** + * Resets the pipeline by removing any existing processors. + * + */ +lunr.Pipeline.prototype.reset = function () { + this._stack = [] +} + +/** + * Returns a representation of the pipeline ready for serialisation. + * + * Logs a warning if the function has not been registered. + * + * @returns {Array} + */ +lunr.Pipeline.prototype.toJSON = function () { + return this._stack.map(function (fn) { + lunr.Pipeline.warnIfFunctionNotRegistered(fn) + + return fn.label + }) +} +/*! + * lunr.Vector + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * A vector is used to construct the vector space of documents and queries. These + * vectors support operations to determine the similarity between two documents or + * a document and a query. + * + * Normally no parameters are required for initializing a vector, but in the case of + * loading a previously dumped vector the raw elements can be provided to the constructor. + * + * For performance reasons vectors are implemented with a flat array, where an elements + * index is immediately followed by its value. E.g. [index, value, index, value]. This + * allows the underlying array to be as sparse as possible and still offer decent + * performance when being used for vector calculations. + * + * @constructor + * @param {Number[]} [elements] - The flat list of element index and element value pairs. + */ +lunr.Vector = function (elements) { + this._magnitude = 0 + this.elements = elements || [] +} + + +/** + * Calculates the position within the vector to insert a given index. + * + * This is used internally by insert and upsert. If there are duplicate indexes then + * the position is returned as if the value for that index were to be updated, but it + * is the callers responsibility to check whether there is a duplicate at that index + * + * @param {Number} insertIdx - The index at which the element should be inserted. + * @returns {Number} + */ +lunr.Vector.prototype.positionForIndex = function (index) { + // For an empty vector the tuple can be inserted at the beginning + if (this.elements.length == 0) { + return 0 + } + + var start = 0, + end = this.elements.length / 2, + sliceLength = end - start, + pivotPoint = Math.floor(sliceLength / 2), + pivotIndex = this.elements[pivotPoint * 2] + + while (sliceLength > 1) { + if (pivotIndex < index) { + start = pivotPoint + } + + if (pivotIndex > index) { + end = pivotPoint + } + + if (pivotIndex == index) { + break + } + + sliceLength = end - start + pivotPoint = start + Math.floor(sliceLength / 2) + pivotIndex = this.elements[pivotPoint * 2] + } + + if (pivotIndex == index) { + return pivotPoint * 2 + } + + if (pivotIndex > index) { + return pivotPoint * 2 + } + + if (pivotIndex < index) { + return (pivotPoint + 1) * 2 + } +} + +/** + * Inserts an element at an index within the vector. + * + * Does not allow duplicates, will throw an error if there is already an entry + * for this index. + * + * @param {Number} insertIdx - The index at which the element should be inserted. + * @param {Number} val - The value to be inserted into the vector. + */ +lunr.Vector.prototype.insert = function (insertIdx, val) { + this.upsert(insertIdx, val, function () { + throw "duplicate index" + }) +} + +/** + * Inserts or updates an existing index within the vector. + * + * @param {Number} insertIdx - The index at which the element should be inserted. + * @param {Number} val - The value to be inserted into the vector. + * @param {function} fn - A function that is called for updates, the existing value and the + * requested value are passed as arguments + */ +lunr.Vector.prototype.upsert = function (insertIdx, val, fn) { + this._magnitude = 0 + var position = this.positionForIndex(insertIdx) + + if (this.elements[position] == insertIdx) { + this.elements[position + 1] = fn(this.elements[position + 1], val) + } else { + this.elements.splice(position, 0, insertIdx, val) + } +} + +/** + * Calculates the magnitude of this vector. + * + * @returns {Number} + */ +lunr.Vector.prototype.magnitude = function () { + if (this._magnitude) return this._magnitude + + var sumOfSquares = 0, + elementsLength = this.elements.length + + for (var i = 1; i < elementsLength; i += 2) { + var val = this.elements[i] + sumOfSquares += val * val + } + + return this._magnitude = Math.sqrt(sumOfSquares) +} + +/** + * Calculates the dot product of this vector and another vector. + * + * @param {lunr.Vector} otherVector - The vector to compute the dot product with. + * @returns {Number} + */ +lunr.Vector.prototype.dot = function (otherVector) { + var dotProduct = 0, + a = this.elements, b = otherVector.elements, + aLen = a.length, bLen = b.length, + aVal = 0, bVal = 0, + i = 0, j = 0 + + while (i < aLen && j < bLen) { + aVal = a[i], bVal = b[j] + if (aVal < bVal) { + i += 2 + } else if (aVal > bVal) { + j += 2 + } else if (aVal == bVal) { + dotProduct += a[i + 1] * b[j + 1] + i += 2 + j += 2 + } + } + + return dotProduct +} + +/** + * Calculates the similarity between this vector and another vector. + * + * @param {lunr.Vector} otherVector - The other vector to calculate the + * similarity with. + * @returns {Number} + */ +lunr.Vector.prototype.similarity = function (otherVector) { + return this.dot(otherVector) / this.magnitude() || 0 +} + +/** + * Converts the vector to an array of the elements within the vector. + * + * @returns {Number[]} + */ +lunr.Vector.prototype.toArray = function () { + var output = new Array (this.elements.length / 2) + + for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) { + output[j] = this.elements[i] + } + + return output +} + +/** + * A JSON serializable representation of the vector. + * + * @returns {Number[]} + */ +lunr.Vector.prototype.toJSON = function () { + return this.elements +} +/* eslint-disable */ +/*! + * lunr.stemmer + * Copyright (C) 2020 Oliver Nightingale + * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt + */ + +/** + * lunr.stemmer is an english language stemmer, this is a JavaScript + * implementation of the PorterStemmer taken from http://tartarus.org/~martin + * + * @static + * @implements {lunr.PipelineFunction} + * @param {lunr.Token} token - The string to stem + * @returns {lunr.Token} + * @see {@link lunr.Pipeline} + * @function + */ +lunr.stemmer = (function(){ + var step2list = { + "ational" : "ate", + "tional" : "tion", + "enci" : "ence", + "anci" : "ance", + "izer" : "ize", + "bli" : "ble", + "alli" : "al", + "entli" : "ent", + "eli" : "e", + "ousli" : "ous", + "ization" : "ize", + "ation" : "ate", + "ator" : "ate", + "alism" : "al", + "iveness" : "ive", + "fulness" : "ful", + "ousness" : "ous", + "aliti" : "al", + "iviti" : "ive", + "biliti" : "ble", + "logi" : "log" + }, + + step3list = { + "icate" : "ic", + "ative" : "", + "alize" : "al", + "iciti" : "ic", + "ical" : "ic", + "ful" : "", + "ness" : "" + }, + + c = "[^aeiou]", // consonant + v = "[aeiouy]", // vowel + C = c + "[^aeiouy]*", // consonant sequence + V = v + "[aeiou]*", // vowel sequence + + mgr0 = "^(" + C + ")?" + V + C, // [C]VC... is m>0 + meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$", // [C]VC[V] is m=1 + mgr1 = "^(" + C + ")?" + V + C + V + C, // [C]VCVC... is m>1 + s_v = "^(" + C + ")?" + v; // vowel in stem + + var re_mgr0 = new RegExp(mgr0); + var re_mgr1 = new RegExp(mgr1); + var re_meq1 = new RegExp(meq1); + var re_s_v = new RegExp(s_v); + + var re_1a = /^(.+?)(ss|i)es$/; + var re2_1a = /^(.+?)([^s])s$/; + var re_1b = /^(.+?)eed$/; + var re2_1b = /^(.+?)(ed|ing)$/; + var re_1b_2 = /.$/; + var re2_1b_2 = /(at|bl|iz)$/; + var re3_1b_2 = new RegExp("([^aeiouylsz])\\1$"); + var re4_1b_2 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + + var re_1c = /^(.+?[^aeiou])y$/; + var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + + var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + + var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + var re2_4 = /^(.+?)(s|t)(ion)$/; + + var re_5 = /^(.+?)e$/; + var re_5_1 = /ll$/; + var re3_5 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + + var porterStemmer = function porterStemmer(w) { + var stem, + suffix, + firstch, + re, + re2, + re3, + re4; + + if (w.length < 3) { return w; } + + firstch = w.substr(0,1); + if (firstch == "y") { + w = firstch.toUpperCase() + w.substr(1); + } + + // Step 1a + re = re_1a + re2 = re2_1a; + + if (re.test(w)) { w = w.replace(re,"$1$2"); } + else if (re2.test(w)) { w = w.replace(re2,"$1$2"); } + + // Step 1b + re = re_1b; + re2 = re2_1b; + if (re.test(w)) { + var fp = re.exec(w); + re = re_mgr0; + if (re.test(fp[1])) { + re = re_1b_2; + w = w.replace(re,""); + } + } else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = re_s_v; + if (re2.test(stem)) { + w = stem; + re2 = re2_1b_2; + re3 = re3_1b_2; + re4 = re4_1b_2; + if (re2.test(w)) { w = w + "e"; } + else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,""); } + else if (re4.test(w)) { w = w + "e"; } + } + } + + // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say) + re = re_1c; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + w = stem + "i"; + } + + // Step 2 + re = re_2; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = re_mgr0; + if (re.test(stem)) { + w = stem + step2list[suffix]; + } + } + + // Step 3 + re = re_3; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = re_mgr0; + if (re.test(stem)) { + w = stem + step3list[suffix]; + } + } + + // Step 4 + re = re_4; + re2 = re2_4; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = re_mgr1; + if (re.test(stem)) { + w = stem; + } + } else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = re_mgr1; + if (re2.test(stem)) { + w = stem; + } + } + + // Step 5 + re = re_5; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = re_mgr1; + re2 = re_meq1; + re3 = re3_5; + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) { + w = stem; + } + } + + re = re_5_1; + re2 = re_mgr1; + if (re.test(w) && re2.test(w)) { + re = re_1b_2; + w = w.replace(re,""); + } + + // and turn initial Y back to y + + if (firstch == "y") { + w = firstch.toLowerCase() + w.substr(1); + } + + return w; + }; + + return function (token) { + return token.update(porterStemmer); + } +})(); + +lunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer') +/*! + * lunr.stopWordFilter + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * lunr.generateStopWordFilter builds a stopWordFilter function from the provided + * list of stop words. + * + * The built in lunr.stopWordFilter is built using this generator and can be used + * to generate custom stopWordFilters for applications or non English languages. + * + * @function + * @param {Array} token The token to pass through the filter + * @returns {lunr.PipelineFunction} + * @see lunr.Pipeline + * @see lunr.stopWordFilter + */ +lunr.generateStopWordFilter = function (stopWords) { + var words = stopWords.reduce(function (memo, stopWord) { + memo[stopWord] = stopWord + return memo + }, {}) + + return function (token) { + if (token && words[token.toString()] !== token.toString()) return token + } +} + +/** + * lunr.stopWordFilter is an English language stop word list filter, any words + * contained in the list will not be passed through the filter. + * + * This is intended to be used in the Pipeline. If the token does not pass the + * filter then undefined will be returned. + * + * @function + * @implements {lunr.PipelineFunction} + * @params {lunr.Token} token - A token to check for being a stop word. + * @returns {lunr.Token} + * @see {@link lunr.Pipeline} + */ +lunr.stopWordFilter = lunr.generateStopWordFilter([ + 'a', + 'able', + 'about', + 'across', + 'after', + 'all', + 'almost', + 'also', + 'am', + 'among', + 'an', + 'and', + 'any', + 'are', + 'as', + 'at', + 'be', + 'because', + 'been', + 'but', + 'by', + 'can', + 'cannot', + 'could', + 'dear', + 'did', + 'do', + 'does', + 'either', + 'else', + 'ever', + 'every', + 'for', + 'from', + 'get', + 'got', + 'had', + 'has', + 'have', + 'he', + 'her', + 'hers', + 'him', + 'his', + 'how', + 'however', + 'i', + 'if', + 'in', + 'into', + 'is', + 'it', + 'its', + 'just', + 'least', + 'let', + 'like', + 'likely', + 'may', + 'me', + 'might', + 'most', + 'must', + 'my', + 'neither', + 'no', + 'nor', + 'not', + 'of', + 'off', + 'often', + 'on', + 'only', + 'or', + 'other', + 'our', + 'own', + 'rather', + 'said', + 'say', + 'says', + 'she', + 'should', + 'since', + 'so', + 'some', + 'than', + 'that', + 'the', + 'their', + 'them', + 'then', + 'there', + 'these', + 'they', + 'this', + 'tis', + 'to', + 'too', + 'twas', + 'us', + 'wants', + 'was', + 'we', + 'were', + 'what', + 'when', + 'where', + 'which', + 'while', + 'who', + 'whom', + 'why', + 'will', + 'with', + 'would', + 'yet', + 'you', + 'your' +]) + +lunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter') +/*! + * lunr.trimmer + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * lunr.trimmer is a pipeline function for trimming non word + * characters from the beginning and end of tokens before they + * enter the index. + * + * This implementation may not work correctly for non latin + * characters and should either be removed or adapted for use + * with languages with non-latin characters. + * + * @static + * @implements {lunr.PipelineFunction} + * @param {lunr.Token} token The token to pass through the filter + * @returns {lunr.Token} + * @see lunr.Pipeline + */ +lunr.trimmer = function (token) { + return token.update(function (s) { + return s.replace(/^\W+/, '').replace(/\W+$/, '') + }) +} + +lunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer') +/*! + * lunr.TokenSet + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * A token set is used to store the unique list of all tokens + * within an index. Token sets are also used to represent an + * incoming query to the index, this query token set and index + * token set are then intersected to find which tokens to look + * up in the inverted index. + * + * A token set can hold multiple tokens, as in the case of the + * index token set, or it can hold a single token as in the + * case of a simple query token set. + * + * Additionally token sets are used to perform wildcard matching. + * Leading, contained and trailing wildcards are supported, and + * from this edit distance matching can also be provided. + * + * Token sets are implemented as a minimal finite state automata, + * where both common prefixes and suffixes are shared between tokens. + * This helps to reduce the space used for storing the token set. + * + * @constructor + */ +lunr.TokenSet = function () { + this.final = false + this.edges = {} + this.id = lunr.TokenSet._nextId + lunr.TokenSet._nextId += 1 +} + +/** + * Keeps track of the next, auto increment, identifier to assign + * to a new tokenSet. + * + * TokenSets require a unique identifier to be correctly minimised. + * + * @private + */ +lunr.TokenSet._nextId = 1 + +/** + * Creates a TokenSet instance from the given sorted array of words. + * + * @param {String[]} arr - A sorted array of strings to create the set from. + * @returns {lunr.TokenSet} + * @throws Will throw an error if the input array is not sorted. + */ +lunr.TokenSet.fromArray = function (arr) { + var builder = new lunr.TokenSet.Builder + + for (var i = 0, len = arr.length; i < len; i++) { + builder.insert(arr[i]) + } + + builder.finish() + return builder.root +} + +/** + * Creates a token set from a query clause. + * + * @private + * @param {Object} clause - A single clause from lunr.Query. + * @param {string} clause.term - The query clause term. + * @param {number} [clause.editDistance] - The optional edit distance for the term. + * @returns {lunr.TokenSet} + */ +lunr.TokenSet.fromClause = function (clause) { + if ('editDistance' in clause) { + return lunr.TokenSet.fromFuzzyString(clause.term, clause.editDistance) + } else { + return lunr.TokenSet.fromString(clause.term) + } +} + +/** + * Creates a token set representing a single string with a specified + * edit distance. + * + * Insertions, deletions, substitutions and transpositions are each + * treated as an edit distance of 1. + * + * Increasing the allowed edit distance will have a dramatic impact + * on the performance of both creating and intersecting these TokenSets. + * It is advised to keep the edit distance less than 3. + * + * @param {string} str - The string to create the token set from. + * @param {number} editDistance - The allowed edit distance to match. + * @returns {lunr.Vector} + */ +lunr.TokenSet.fromFuzzyString = function (str, editDistance) { + var root = new lunr.TokenSet + + var stack = [{ + node: root, + editsRemaining: editDistance, + str: str + }] + + while (stack.length) { + var frame = stack.pop() + + // no edit + if (frame.str.length > 0) { + var char = frame.str.charAt(0), + noEditNode + + if (char in frame.node.edges) { + noEditNode = frame.node.edges[char] + } else { + noEditNode = new lunr.TokenSet + frame.node.edges[char] = noEditNode + } + + if (frame.str.length == 1) { + noEditNode.final = true + } + + stack.push({ + node: noEditNode, + editsRemaining: frame.editsRemaining, + str: frame.str.slice(1) + }) + } + + if (frame.editsRemaining == 0) { + continue + } + + // insertion + if ("*" in frame.node.edges) { + var insertionNode = frame.node.edges["*"] + } else { + var insertionNode = new lunr.TokenSet + frame.node.edges["*"] = insertionNode + } + + if (frame.str.length == 0) { + insertionNode.final = true + } + + stack.push({ + node: insertionNode, + editsRemaining: frame.editsRemaining - 1, + str: frame.str + }) + + // deletion + // can only do a deletion if we have enough edits remaining + // and if there are characters left to delete in the string + if (frame.str.length > 1) { + stack.push({ + node: frame.node, + editsRemaining: frame.editsRemaining - 1, + str: frame.str.slice(1) + }) + } + + // deletion + // just removing the last character from the str + if (frame.str.length == 1) { + frame.node.final = true + } + + // substitution + // can only do a substitution if we have enough edits remaining + // and if there are characters left to substitute + if (frame.str.length >= 1) { + if ("*" in frame.node.edges) { + var substitutionNode = frame.node.edges["*"] + } else { + var substitutionNode = new lunr.TokenSet + frame.node.edges["*"] = substitutionNode + } + + if (frame.str.length == 1) { + substitutionNode.final = true + } + + stack.push({ + node: substitutionNode, + editsRemaining: frame.editsRemaining - 1, + str: frame.str.slice(1) + }) + } + + // transposition + // can only do a transposition if there are edits remaining + // and there are enough characters to transpose + if (frame.str.length > 1) { + var charA = frame.str.charAt(0), + charB = frame.str.charAt(1), + transposeNode + + if (charB in frame.node.edges) { + transposeNode = frame.node.edges[charB] + } else { + transposeNode = new lunr.TokenSet + frame.node.edges[charB] = transposeNode + } + + if (frame.str.length == 1) { + transposeNode.final = true + } + + stack.push({ + node: transposeNode, + editsRemaining: frame.editsRemaining - 1, + str: charA + frame.str.slice(2) + }) + } + } + + return root +} + +/** + * Creates a TokenSet from a string. + * + * The string may contain one or more wildcard characters (*) + * that will allow wildcard matching when intersecting with + * another TokenSet. + * + * @param {string} str - The string to create a TokenSet from. + * @returns {lunr.TokenSet} + */ +lunr.TokenSet.fromString = function (str) { + var node = new lunr.TokenSet, + root = node + + /* + * Iterates through all characters within the passed string + * appending a node for each character. + * + * When a wildcard character is found then a self + * referencing edge is introduced to continually match + * any number of any characters. + */ + for (var i = 0, len = str.length; i < len; i++) { + var char = str[i], + final = (i == len - 1) + + if (char == "*") { + node.edges[char] = node + node.final = final + + } else { + var next = new lunr.TokenSet + next.final = final + + node.edges[char] = next + node = next + } + } + + return root +} + +/** + * Converts this TokenSet into an array of strings + * contained within the TokenSet. + * + * This is not intended to be used on a TokenSet that + * contains wildcards, in these cases the results are + * undefined and are likely to cause an infinite loop. + * + * @returns {string[]} + */ +lunr.TokenSet.prototype.toArray = function () { + var words = [] + + var stack = [{ + prefix: "", + node: this + }] + + while (stack.length) { + var frame = stack.pop(), + edges = Object.keys(frame.node.edges), + len = edges.length + + if (frame.node.final) { + /* In Safari, at this point the prefix is sometimes corrupted, see: + * https://github.com/olivernn/lunr.js/issues/279 Calling any + * String.prototype method forces Safari to "cast" this string to what + * it's supposed to be, fixing the bug. */ + frame.prefix.charAt(0) + words.push(frame.prefix) + } + + for (var i = 0; i < len; i++) { + var edge = edges[i] + + stack.push({ + prefix: frame.prefix.concat(edge), + node: frame.node.edges[edge] + }) + } + } + + return words +} + +/** + * Generates a string representation of a TokenSet. + * + * This is intended to allow TokenSets to be used as keys + * in objects, largely to aid the construction and minimisation + * of a TokenSet. As such it is not designed to be a human + * friendly representation of the TokenSet. + * + * @returns {string} + */ +lunr.TokenSet.prototype.toString = function () { + // NOTE: Using Object.keys here as this.edges is very likely + // to enter 'hash-mode' with many keys being added + // + // avoiding a for-in loop here as it leads to the function + // being de-optimised (at least in V8). From some simple + // benchmarks the performance is comparable, but allowing + // V8 to optimize may mean easy performance wins in the future. + + if (this._str) { + return this._str + } + + var str = this.final ? '1' : '0', + labels = Object.keys(this.edges).sort(), + len = labels.length + + for (var i = 0; i < len; i++) { + var label = labels[i], + node = this.edges[label] + + str = str + label + node.id + } + + return str +} + +/** + * Returns a new TokenSet that is the intersection of + * this TokenSet and the passed TokenSet. + * + * This intersection will take into account any wildcards + * contained within the TokenSet. + * + * @param {lunr.TokenSet} b - An other TokenSet to intersect with. + * @returns {lunr.TokenSet} + */ +lunr.TokenSet.prototype.intersect = function (b) { + var output = new lunr.TokenSet, + frame = undefined + + var stack = [{ + qNode: b, + output: output, + node: this + }] + + while (stack.length) { + frame = stack.pop() + + // NOTE: As with the #toString method, we are using + // Object.keys and a for loop instead of a for-in loop + // as both of these objects enter 'hash' mode, causing + // the function to be de-optimised in V8 + var qEdges = Object.keys(frame.qNode.edges), + qLen = qEdges.length, + nEdges = Object.keys(frame.node.edges), + nLen = nEdges.length + + for (var q = 0; q < qLen; q++) { + var qEdge = qEdges[q] + + for (var n = 0; n < nLen; n++) { + var nEdge = nEdges[n] + + if (nEdge == qEdge || qEdge == '*') { + var node = frame.node.edges[nEdge], + qNode = frame.qNode.edges[qEdge], + final = node.final && qNode.final, + next = undefined + + if (nEdge in frame.output.edges) { + // an edge already exists for this character + // no need to create a new node, just set the finality + // bit unless this node is already final + next = frame.output.edges[nEdge] + next.final = next.final || final + + } else { + // no edge exists yet, must create one + // set the finality bit and insert it + // into the output + next = new lunr.TokenSet + next.final = final + frame.output.edges[nEdge] = next + } + + stack.push({ + qNode: qNode, + output: next, + node: node + }) + } + } + } + } + + return output +} +lunr.TokenSet.Builder = function () { + this.previousWord = "" + this.root = new lunr.TokenSet + this.uncheckedNodes = [] + this.minimizedNodes = {} +} + +lunr.TokenSet.Builder.prototype.insert = function (word) { + var node, + commonPrefix = 0 + + if (word < this.previousWord) { + throw new Error ("Out of order word insertion") + } + + for (var i = 0; i < word.length && i < this.previousWord.length; i++) { + if (word[i] != this.previousWord[i]) break + commonPrefix++ + } + + this.minimize(commonPrefix) + + if (this.uncheckedNodes.length == 0) { + node = this.root + } else { + node = this.uncheckedNodes[this.uncheckedNodes.length - 1].child + } + + for (var i = commonPrefix; i < word.length; i++) { + var nextNode = new lunr.TokenSet, + char = word[i] + + node.edges[char] = nextNode + + this.uncheckedNodes.push({ + parent: node, + char: char, + child: nextNode + }) + + node = nextNode + } + + node.final = true + this.previousWord = word +} + +lunr.TokenSet.Builder.prototype.finish = function () { + this.minimize(0) +} + +lunr.TokenSet.Builder.prototype.minimize = function (downTo) { + for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) { + var node = this.uncheckedNodes[i], + childKey = node.child.toString() + + if (childKey in this.minimizedNodes) { + node.parent.edges[node.char] = this.minimizedNodes[childKey] + } else { + // Cache the key for this node since + // we know it can't change anymore + node.child._str = childKey + + this.minimizedNodes[childKey] = node.child + } + + this.uncheckedNodes.pop() + } +} +/*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * An index contains the built index of all documents and provides a query interface + * to the index. + * + * Usually instances of lunr.Index will not be created using this constructor, instead + * lunr.Builder should be used to construct new indexes, or lunr.Index.load should be + * used to load previously built and serialized indexes. + * + * @constructor + * @param {Object} attrs - The attributes of the built search index. + * @param {Object} attrs.invertedIndex - An index of term/field to document reference. + * @param {Object} attrs.fieldVectors - Field vectors + * @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens. + * @param {string[]} attrs.fields - The names of indexed document fields. + * @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms. + */ +lunr.Index = function (attrs) { + this.invertedIndex = attrs.invertedIndex + this.fieldVectors = attrs.fieldVectors + this.tokenSet = attrs.tokenSet + this.fields = attrs.fields + this.pipeline = attrs.pipeline +} + +/** + * A result contains details of a document matching a search query. + * @typedef {Object} lunr.Index~Result + * @property {string} ref - The reference of the document this result represents. + * @property {number} score - A number between 0 and 1 representing how similar this document is to the query. + * @property {lunr.MatchData} matchData - Contains metadata about this match including which term(s) caused the match. + */ + +/** + * Although lunr provides the ability to create queries using lunr.Query, it also provides a simple + * query language which itself is parsed into an instance of lunr.Query. + * + * For programmatically building queries it is advised to directly use lunr.Query, the query language + * is best used for human entered text rather than program generated text. + * + * At its simplest queries can just be a single term, e.g. `hello`, multiple terms are also supported + * and will be combined with OR, e.g `hello world` will match documents that contain either 'hello' + * or 'world', though those that contain both will rank higher in the results. + * + * Wildcards can be included in terms to match one or more unspecified characters, these wildcards can + * be inserted anywhere within the term, and more than one wildcard can exist in a single term. Adding + * wildcards will increase the number of documents that will be found but can also have a negative + * impact on query performance, especially with wildcards at the beginning of a term. + * + * Terms can be restricted to specific fields, e.g. `title:hello`, only documents with the term + * hello in the title field will match this query. Using a field not present in the index will lead + * to an error being thrown. + * + * Modifiers can also be added to terms, lunr supports edit distance and boost modifiers on terms. A term + * boost will make documents matching that term score higher, e.g. `foo^5`. Edit distance is also supported + * to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2. + * Avoid large values for edit distance to improve query performance. + * + * Each term also supports a presence modifier. By default a term's presence in document is optional, however + * this can be changed to either required or prohibited. For a term's presence to be required in a document the + * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and + * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not + * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'. + * + * To escape special characters the backslash character '\' can be used, this allows searches to include + * characters that would normally be considered modifiers, e.g. `foo\~2` will search for a term "foo~2" instead + * of attempting to apply a boost of 2 to the search term "foo". + * + * @typedef {string} lunr.Index~QueryString + * @example Simple single term query + * hello + * @example Multiple term query + * hello world + * @example term scoped to a field + * title:hello + * @example term with a boost of 10 + * hello^10 + * @example term with an edit distance of 2 + * hello~2 + * @example terms with presence modifiers + * -foo +bar baz + */ + +/** + * Performs a search against the index using lunr query syntax. + * + * Results will be returned sorted by their score, the most relevant results + * will be returned first. For details on how the score is calculated, please see + * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}. + * + * For more programmatic querying use lunr.Index#query. + * + * @param {lunr.Index~QueryString} queryString - A string containing a lunr query. + * @throws {lunr.QueryParseError} If the passed query string cannot be parsed. + * @returns {lunr.Index~Result[]} + */ +lunr.Index.prototype.search = function (queryString) { + return this.query(function (query) { + var parser = new lunr.QueryParser(queryString, query) + parser.parse() + }) +} + +/** + * A query builder callback provides a query object to be used to express + * the query to perform on the index. + * + * @callback lunr.Index~queryBuilder + * @param {lunr.Query} query - The query object to build up. + * @this lunr.Query + */ + +/** + * Performs a query against the index using the yielded lunr.Query object. + * + * If performing programmatic queries against the index, this method is preferred + * over lunr.Index#search so as to avoid the additional query parsing overhead. + * + * A query object is yielded to the supplied function which should be used to + * express the query to be run against the index. + * + * Note that although this function takes a callback parameter it is _not_ an + * asynchronous operation, the callback is just yielded a query object to be + * customized. + * + * @param {lunr.Index~queryBuilder} fn - A function that is used to build the query. + * @returns {lunr.Index~Result[]} + */ +lunr.Index.prototype.query = function (fn) { + // for each query clause + // * process terms + // * expand terms from token set + // * find matching documents and metadata + // * get document vectors + // * score documents + + var query = new lunr.Query(this.fields), + matchingFields = Object.create(null), + queryVectors = Object.create(null), + termFieldCache = Object.create(null), + requiredMatches = Object.create(null), + prohibitedMatches = Object.create(null) + + /* + * To support field level boosts a query vector is created per + * field. An empty vector is eagerly created to support negated + * queries. + */ + for (var i = 0; i < this.fields.length; i++) { + queryVectors[this.fields[i]] = new lunr.Vector + } + + fn.call(query, query) + + for (var i = 0; i < query.clauses.length; i++) { + /* + * Unless the pipeline has been disabled for this term, which is + * the case for terms with wildcards, we need to pass the clause + * term through the search pipeline. A pipeline returns an array + * of processed terms. Pipeline functions may expand the passed + * term, which means we may end up performing multiple index lookups + * for a single query term. + */ + var clause = query.clauses[i], + terms = null, + clauseMatches = lunr.Set.empty + + if (clause.usePipeline) { + terms = this.pipeline.runString(clause.term, { + fields: clause.fields + }) + } else { + terms = [clause.term] + } + + for (var m = 0; m < terms.length; m++) { + var term = terms[m] + + /* + * Each term returned from the pipeline needs to use the same query + * clause object, e.g. the same boost and or edit distance. The + * simplest way to do this is to re-use the clause object but mutate + * its term property. + */ + clause.term = term + + /* + * From the term in the clause we create a token set which will then + * be used to intersect the indexes token set to get a list of terms + * to lookup in the inverted index + */ + var termTokenSet = lunr.TokenSet.fromClause(clause), + expandedTerms = this.tokenSet.intersect(termTokenSet).toArray() + + /* + * If a term marked as required does not exist in the tokenSet it is + * impossible for the search to return any matches. We set all the field + * scoped required matches set to empty and stop examining any further + * clauses. + */ + if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) { + for (var k = 0; k < clause.fields.length; k++) { + var field = clause.fields[k] + requiredMatches[field] = lunr.Set.empty + } + + break + } + + for (var j = 0; j < expandedTerms.length; j++) { + /* + * For each term get the posting and termIndex, this is required for + * building the query vector. + */ + var expandedTerm = expandedTerms[j], + posting = this.invertedIndex[expandedTerm], + termIndex = posting._index + + for (var k = 0; k < clause.fields.length; k++) { + /* + * For each field that this query term is scoped by (by default + * all fields are in scope) we need to get all the document refs + * that have this term in that field. + * + * The posting is the entry in the invertedIndex for the matching + * term from above. + */ + var field = clause.fields[k], + fieldPosting = posting[field], + matchingDocumentRefs = Object.keys(fieldPosting), + termField = expandedTerm + "/" + field, + matchingDocumentsSet = new lunr.Set(matchingDocumentRefs) + + /* + * if the presence of this term is required ensure that the matching + * documents are added to the set of required matches for this clause. + * + */ + if (clause.presence == lunr.Query.presence.REQUIRED) { + clauseMatches = clauseMatches.union(matchingDocumentsSet) + + if (requiredMatches[field] === undefined) { + requiredMatches[field] = lunr.Set.complete + } + } + + /* + * if the presence of this term is prohibited ensure that the matching + * documents are added to the set of prohibited matches for this field, + * creating that set if it does not yet exist. + */ + if (clause.presence == lunr.Query.presence.PROHIBITED) { + if (prohibitedMatches[field] === undefined) { + prohibitedMatches[field] = lunr.Set.empty + } + + prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet) + + /* + * Prohibited matches should not be part of the query vector used for + * similarity scoring and no metadata should be extracted so we continue + * to the next field + */ + continue + } + + /* + * The query field vector is populated using the termIndex found for + * the term and a unit value with the appropriate boost applied. + * Using upsert because there could already be an entry in the vector + * for the term we are working with. In that case we just add the scores + * together. + */ + queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b }) + + /** + * If we've already seen this term, field combo then we've already collected + * the matching documents and metadata, no need to go through all that again + */ + if (termFieldCache[termField]) { + continue + } + + for (var l = 0; l < matchingDocumentRefs.length; l++) { + /* + * All metadata for this term/field/document triple + * are then extracted and collected into an instance + * of lunr.MatchData ready to be returned in the query + * results + */ + var matchingDocumentRef = matchingDocumentRefs[l], + matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field), + metadata = fieldPosting[matchingDocumentRef], + fieldMatch + + if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) { + matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata) + } else { + fieldMatch.add(expandedTerm, field, metadata) + } + + } + + termFieldCache[termField] = true + } + } + } + + /** + * If the presence was required we need to update the requiredMatches field sets. + * We do this after all fields for the term have collected their matches because + * the clause terms presence is required in _any_ of the fields not _all_ of the + * fields. + */ + if (clause.presence === lunr.Query.presence.REQUIRED) { + for (var k = 0; k < clause.fields.length; k++) { + var field = clause.fields[k] + requiredMatches[field] = requiredMatches[field].intersect(clauseMatches) + } + } + } + + /** + * Need to combine the field scoped required and prohibited + * matching documents into a global set of required and prohibited + * matches + */ + var allRequiredMatches = lunr.Set.complete, + allProhibitedMatches = lunr.Set.empty + + for (var i = 0; i < this.fields.length; i++) { + var field = this.fields[i] + + if (requiredMatches[field]) { + allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field]) + } + + if (prohibitedMatches[field]) { + allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field]) + } + } + + var matchingFieldRefs = Object.keys(matchingFields), + results = [], + matches = Object.create(null) + + /* + * If the query is negated (contains only prohibited terms) + * we need to get _all_ fieldRefs currently existing in the + * index. This is only done when we know that the query is + * entirely prohibited terms to avoid any cost of getting all + * fieldRefs unnecessarily. + * + * Additionally, blank MatchData must be created to correctly + * populate the results. + */ + if (query.isNegated()) { + matchingFieldRefs = Object.keys(this.fieldVectors) + + for (var i = 0; i < matchingFieldRefs.length; i++) { + var matchingFieldRef = matchingFieldRefs[i] + var fieldRef = lunr.FieldRef.fromString(matchingFieldRef) + matchingFields[matchingFieldRef] = new lunr.MatchData + } + } + + for (var i = 0; i < matchingFieldRefs.length; i++) { + /* + * Currently we have document fields that match the query, but we + * need to return documents. The matchData and scores are combined + * from multiple fields belonging to the same document. + * + * Scores are calculated by field, using the query vectors created + * above, and combined into a final document score using addition. + */ + var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]), + docRef = fieldRef.docRef + + if (!allRequiredMatches.contains(docRef)) { + continue + } + + if (allProhibitedMatches.contains(docRef)) { + continue + } + + var fieldVector = this.fieldVectors[fieldRef], + score = queryVectors[fieldRef.fieldName].similarity(fieldVector), + docMatch + + if ((docMatch = matches[docRef]) !== undefined) { + docMatch.score += score + docMatch.matchData.combine(matchingFields[fieldRef]) + } else { + var match = { + ref: docRef, + score: score, + matchData: matchingFields[fieldRef] + } + matches[docRef] = match + results.push(match) + } + } + + /* + * Sort the results objects by score, highest first. + */ + return results.sort(function (a, b) { + return b.score - a.score + }) +} + +/** + * Prepares the index for JSON serialization. + * + * The schema for this JSON blob will be described in a + * separate JSON schema file. + * + * @returns {Object} + */ +lunr.Index.prototype.toJSON = function () { + var invertedIndex = Object.keys(this.invertedIndex) + .sort() + .map(function (term) { + return [term, this.invertedIndex[term]] + }, this) + + var fieldVectors = Object.keys(this.fieldVectors) + .map(function (ref) { + return [ref, this.fieldVectors[ref].toJSON()] + }, this) + + return { + version: lunr.version, + fields: this.fields, + fieldVectors: fieldVectors, + invertedIndex: invertedIndex, + pipeline: this.pipeline.toJSON() + } +} + +/** + * Loads a previously serialized lunr.Index + * + * @param {Object} serializedIndex - A previously serialized lunr.Index + * @returns {lunr.Index} + */ +lunr.Index.load = function (serializedIndex) { + var attrs = {}, + fieldVectors = {}, + serializedVectors = serializedIndex.fieldVectors, + invertedIndex = Object.create(null), + serializedInvertedIndex = serializedIndex.invertedIndex, + tokenSetBuilder = new lunr.TokenSet.Builder, + pipeline = lunr.Pipeline.load(serializedIndex.pipeline) + + if (serializedIndex.version != lunr.version) { + lunr.utils.warn("Version mismatch when loading serialised index. Current version of lunr '" + lunr.version + "' does not match serialized index '" + serializedIndex.version + "'") + } + + for (var i = 0; i < serializedVectors.length; i++) { + var tuple = serializedVectors[i], + ref = tuple[0], + elements = tuple[1] + + fieldVectors[ref] = new lunr.Vector(elements) + } + + for (var i = 0; i < serializedInvertedIndex.length; i++) { + var tuple = serializedInvertedIndex[i], + term = tuple[0], + posting = tuple[1] + + tokenSetBuilder.insert(term) + invertedIndex[term] = posting + } + + tokenSetBuilder.finish() + + attrs.fields = serializedIndex.fields + + attrs.fieldVectors = fieldVectors + attrs.invertedIndex = invertedIndex + attrs.tokenSet = tokenSetBuilder.root + attrs.pipeline = pipeline + + return new lunr.Index(attrs) +} +/*! + * lunr.Builder + * Copyright (C) 2020 Oliver Nightingale + */ + +/** + * lunr.Builder performs indexing on a set of documents and + * returns instances of lunr.Index ready for querying. + * + * All configuration of the index is done via the builder, the + * fields to index, the document reference, the text processing + * pipeline and document scoring parameters are all set on the + * builder before indexing. + * + * @constructor + * @property {string} _ref - Internal reference to the document reference field. + * @property {string[]} _fields - Internal reference to the document fields to index. + * @property {object} invertedIndex - The inverted index maps terms to document fields. + * @property {object} documentTermFrequencies - Keeps track of document term frequencies. + * @property {object} documentLengths - Keeps track of the length of documents added to the index. + * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing. + * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing. + * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index. + * @property {number} documentCount - Keeps track of the total number of documents indexed. + * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75. + * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2. + * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space. + * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index. + */ +lunr.Builder = function () { + this._ref = "id" + this._fields = Object.create(null) + this._documents = Object.create(null) + this.invertedIndex = Object.create(null) + this.fieldTermFrequencies = {} + this.fieldLengths = {} + this.tokenizer = lunr.tokenizer + this.pipeline = new lunr.Pipeline + this.searchPipeline = new lunr.Pipeline + this.documentCount = 0 + this._b = 0.75 + this._k1 = 1.2 + this.termIndex = 0 + this.metadataWhitelist = [] +} + +/** + * Sets the document field used as the document reference. Every document must have this field. + * The type of this field in the document should be a string, if it is not a string it will be + * coerced into a string by calling toString. + * + * The default ref is 'id'. + * + * The ref should _not_ be changed during indexing, it should be set before any documents are + * added to the index. Changing it during indexing can lead to inconsistent results. + * + * @param {string} ref - The name of the reference field in the document. + */ +lunr.Builder.prototype.ref = function (ref) { + this._ref = ref +} + +/** + * A function that is used to extract a field from a document. + * + * Lunr expects a field to be at the top level of a document, if however the field + * is deeply nested within a document an extractor function can be used to extract + * the right field for indexing. + * + * @callback fieldExtractor + * @param {object} doc - The document being added to the index. + * @returns {?(string|object|object[])} obj - The object that will be indexed for this field. + * @example Extracting a nested field + * function (doc) { return doc.nested.field } + */ + +/** + * Adds a field to the list of document fields that will be indexed. Every document being + * indexed should have this field. Null values for this field in indexed documents will + * not cause errors but will limit the chance of that document being retrieved by searches. + * + * All fields should be added before adding documents to the index. Adding fields after + * a document has been indexed will have no effect on already indexed documents. + * + * Fields can be boosted at build time. This allows terms within that field to have more + * importance when ranking search results. Use a field boost to specify that matches within + * one field are more important than other fields. + * + * @param {string} fieldName - The name of a field to index in all documents. + * @param {object} attributes - Optional attributes associated with this field. + * @param {number} [attributes.boost=1] - Boost applied to all terms within this field. + * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document. + * @throws {RangeError} fieldName cannot contain unsupported characters '/' + */ +lunr.Builder.prototype.field = function (fieldName, attributes) { + if (/\//.test(fieldName)) { + throw new RangeError ("Field '" + fieldName + "' contains illegal character '/'") + } + + this._fields[fieldName] = attributes || {} +} + +/** + * A parameter to tune the amount of field length normalisation that is applied when + * calculating relevance scores. A value of 0 will completely disable any normalisation + * and a value of 1 will fully normalise field lengths. The default is 0.75. Values of b + * will be clamped to the range 0 - 1. + * + * @param {number} number - The value to set for this tuning parameter. + */ +lunr.Builder.prototype.b = function (number) { + if (number < 0) { + this._b = 0 + } else if (number > 1) { + this._b = 1 + } else { + this._b = number + } +} + +/** + * A parameter that controls the speed at which a rise in term frequency results in term + * frequency saturation. The default value is 1.2. Setting this to a higher value will give + * slower saturation levels, a lower value will result in quicker saturation. + * + * @param {number} number - The value to set for this tuning parameter. + */ +lunr.Builder.prototype.k1 = function (number) { + this._k1 = number +} + +/** + * Adds a document to the index. + * + * Before adding fields to the index the index should have been fully setup, with the document + * ref and all fields to index already having been specified. + * + * The document must have a field name as specified by the ref (by default this is 'id') and + * it should have all fields defined for indexing, though null or undefined values will not + * cause errors. + * + * Entire documents can be boosted at build time. Applying a boost to a document indicates that + * this document should rank higher in search results than other documents. + * + * @param {object} doc - The document to add to the index. + * @param {object} attributes - Optional attributes associated with this document. + * @param {number} [attributes.boost=1] - Boost applied to all terms within this document. + */ +lunr.Builder.prototype.add = function (doc, attributes) { + var docRef = doc[this._ref], + fields = Object.keys(this._fields) + + this._documents[docRef] = attributes || {} + this.documentCount += 1 + + for (var i = 0; i < fields.length; i++) { + var fieldName = fields[i], + extractor = this._fields[fieldName].extractor, + field = extractor ? extractor(doc) : doc[fieldName], + tokens = this.tokenizer(field, { + fields: [fieldName] + }), + terms = this.pipeline.run(tokens), + fieldRef = new lunr.FieldRef (docRef, fieldName), + fieldTerms = Object.create(null) + + this.fieldTermFrequencies[fieldRef] = fieldTerms + this.fieldLengths[fieldRef] = 0 + + // store the length of this field for this document + this.fieldLengths[fieldRef] += terms.length + + // calculate term frequencies for this field + for (var j = 0; j < terms.length; j++) { + var term = terms[j] + + if (fieldTerms[term] == undefined) { + fieldTerms[term] = 0 + } + + fieldTerms[term] += 1 + + // add to inverted index + // create an initial posting if one doesn't exist + if (this.invertedIndex[term] == undefined) { + var posting = Object.create(null) + posting["_index"] = this.termIndex + this.termIndex += 1 + + for (var k = 0; k < fields.length; k++) { + posting[fields[k]] = Object.create(null) + } + + this.invertedIndex[term] = posting + } + + // add an entry for this term/fieldName/docRef to the invertedIndex + if (this.invertedIndex[term][fieldName][docRef] == undefined) { + this.invertedIndex[term][fieldName][docRef] = Object.create(null) + } + + // store all whitelisted metadata about this token in the + // inverted index + for (var l = 0; l < this.metadataWhitelist.length; l++) { + var metadataKey = this.metadataWhitelist[l], + metadata = term.metadata[metadataKey] + + if (this.invertedIndex[term][fieldName][docRef][metadataKey] == undefined) { + this.invertedIndex[term][fieldName][docRef][metadataKey] = [] + } + + this.invertedIndex[term][fieldName][docRef][metadataKey].push(metadata) + } + } + + } +} + +/** + * Calculates the average document length for this index + * + * @private + */ +lunr.Builder.prototype.calculateAverageFieldLengths = function () { + + var fieldRefs = Object.keys(this.fieldLengths), + numberOfFields = fieldRefs.length, + accumulator = {}, + documentsWithField = {} + + for (var i = 0; i < numberOfFields; i++) { + var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]), + field = fieldRef.fieldName + + documentsWithField[field] || (documentsWithField[field] = 0) + documentsWithField[field] += 1 + + accumulator[field] || (accumulator[field] = 0) + accumulator[field] += this.fieldLengths[fieldRef] + } + + var fields = Object.keys(this._fields) + + for (var i = 0; i < fields.length; i++) { + var fieldName = fields[i] + accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName] + } + + this.averageFieldLength = accumulator +} + +/** + * Builds a vector space model of every document using lunr.Vector + * + * @private + */ +lunr.Builder.prototype.createFieldVectors = function () { + var fieldVectors = {}, + fieldRefs = Object.keys(this.fieldTermFrequencies), + fieldRefsLength = fieldRefs.length, + termIdfCache = Object.create(null) + + for (var i = 0; i < fieldRefsLength; i++) { + var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]), + fieldName = fieldRef.fieldName, + fieldLength = this.fieldLengths[fieldRef], + fieldVector = new lunr.Vector, + termFrequencies = this.fieldTermFrequencies[fieldRef], + terms = Object.keys(termFrequencies), + termsLength = terms.length + + + var fieldBoost = this._fields[fieldName].boost || 1, + docBoost = this._documents[fieldRef.docRef].boost || 1 + + for (var j = 0; j < termsLength; j++) { + var term = terms[j], + tf = termFrequencies[term], + termIndex = this.invertedIndex[term]._index, + idf, score, scoreWithPrecision + + if (termIdfCache[term] === undefined) { + idf = lunr.idf(this.invertedIndex[term], this.documentCount) + termIdfCache[term] = idf + } else { + idf = termIdfCache[term] + } + + score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf) + score *= fieldBoost + score *= docBoost + scoreWithPrecision = Math.round(score * 1000) / 1000 + // Converts 1.23456789 to 1.234. + // Reducing the precision so that the vectors take up less + // space when serialised. Doing it now so that they behave + // the same before and after serialisation. Also, this is + // the fastest approach to reducing a number's precision in + // JavaScript. + + fieldVector.insert(termIndex, scoreWithPrecision) + } + + fieldVectors[fieldRef] = fieldVector + } + + this.fieldVectors = fieldVectors +} + +/** + * Creates a token set of all tokens in the index using lunr.TokenSet + * + * @private + */ +lunr.Builder.prototype.createTokenSet = function () { + this.tokenSet = lunr.TokenSet.fromArray( + Object.keys(this.invertedIndex).sort() + ) +} + +/** + * Builds the index, creating an instance of lunr.Index. + * + * This completes the indexing process and should only be called + * once all documents have been added to the index. + * + * @returns {lunr.Index} + */ +lunr.Builder.prototype.build = function () { + this.calculateAverageFieldLengths() + this.createFieldVectors() + this.createTokenSet() + + return new lunr.Index({ + invertedIndex: this.invertedIndex, + fieldVectors: this.fieldVectors, + tokenSet: this.tokenSet, + fields: Object.keys(this._fields), + pipeline: this.searchPipeline + }) +} + +/** + * Applies a plugin to the index builder. + * + * A plugin is a function that is called with the index builder as its context. + * Plugins can be used to customise or extend the behaviour of the index + * in some way. A plugin is just a function, that encapsulated the custom + * behaviour that should be applied when building the index. + * + * The plugin function will be called with the index builder as its argument, additional + * arguments can also be passed when calling use. The function will be called + * with the index builder as its context. + * + * @param {Function} plugin The plugin to apply. + */ +lunr.Builder.prototype.use = function (fn) { + var args = Array.prototype.slice.call(arguments, 1) + args.unshift(this) + fn.apply(this, args) +} +/** + * Contains and collects metadata about a matching document. + * A single instance of lunr.MatchData is returned as part of every + * lunr.Index~Result. + * + * @constructor + * @param {string} term - The term this match data is associated with + * @param {string} field - The field in which the term was found + * @param {object} metadata - The metadata recorded about this term in this field + * @property {object} metadata - A cloned collection of metadata associated with this document. + * @see {@link lunr.Index~Result} + */ +lunr.MatchData = function (term, field, metadata) { + var clonedMetadata = Object.create(null), + metadataKeys = Object.keys(metadata || {}) + + // Cloning the metadata to prevent the original + // being mutated during match data combination. + // Metadata is kept in an array within the inverted + // index so cloning the data can be done with + // Array#slice + for (var i = 0; i < metadataKeys.length; i++) { + var key = metadataKeys[i] + clonedMetadata[key] = metadata[key].slice() + } + + this.metadata = Object.create(null) + + if (term !== undefined) { + this.metadata[term] = Object.create(null) + this.metadata[term][field] = clonedMetadata + } +} + +/** + * An instance of lunr.MatchData will be created for every term that matches a + * document. However only one instance is required in a lunr.Index~Result. This + * method combines metadata from another instance of lunr.MatchData with this + * objects metadata. + * + * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one. + * @see {@link lunr.Index~Result} + */ +lunr.MatchData.prototype.combine = function (otherMatchData) { + var terms = Object.keys(otherMatchData.metadata) + + for (var i = 0; i < terms.length; i++) { + var term = terms[i], + fields = Object.keys(otherMatchData.metadata[term]) + + if (this.metadata[term] == undefined) { + this.metadata[term] = Object.create(null) + } + + for (var j = 0; j < fields.length; j++) { + var field = fields[j], + keys = Object.keys(otherMatchData.metadata[term][field]) + + if (this.metadata[term][field] == undefined) { + this.metadata[term][field] = Object.create(null) + } + + for (var k = 0; k < keys.length; k++) { + var key = keys[k] + + if (this.metadata[term][field][key] == undefined) { + this.metadata[term][field][key] = otherMatchData.metadata[term][field][key] + } else { + this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key]) + } + + } + } + } +} + +/** + * Add metadata for a term/field pair to this instance of match data. + * + * @param {string} term - The term this match data is associated with + * @param {string} field - The field in which the term was found + * @param {object} metadata - The metadata recorded about this term in this field + */ +lunr.MatchData.prototype.add = function (term, field, metadata) { + if (!(term in this.metadata)) { + this.metadata[term] = Object.create(null) + this.metadata[term][field] = metadata + return + } + + if (!(field in this.metadata[term])) { + this.metadata[term][field] = metadata + return + } + + var metadataKeys = Object.keys(metadata) + + for (var i = 0; i < metadataKeys.length; i++) { + var key = metadataKeys[i] + + if (key in this.metadata[term][field]) { + this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key]) + } else { + this.metadata[term][field][key] = metadata[key] + } + } +} +/** + * A lunr.Query provides a programmatic way of defining queries to be performed + * against a {@link lunr.Index}. + * + * Prefer constructing a lunr.Query using the {@link lunr.Index#query} method + * so the query object is pre-initialized with the right index fields. + * + * @constructor + * @property {lunr.Query~Clause[]} clauses - An array of query clauses. + * @property {string[]} allFields - An array of all available fields in a lunr.Index. + */ +lunr.Query = function (allFields) { + this.clauses = [] + this.allFields = allFields +} + +/** + * Constants for indicating what kind of automatic wildcard insertion will be used when constructing a query clause. + * + * This allows wildcards to be added to the beginning and end of a term without having to manually do any string + * concatenation. + * + * The wildcard constants can be bitwise combined to select both leading and trailing wildcards. + * + * @constant + * @default + * @property {number} wildcard.NONE - The term will have no wildcards inserted, this is the default behaviour + * @property {number} wildcard.LEADING - Prepend the term with a wildcard, unless a leading wildcard already exists + * @property {number} wildcard.TRAILING - Append a wildcard to the term, unless a trailing wildcard already exists + * @see lunr.Query~Clause + * @see lunr.Query#clause + * @see lunr.Query#term + * @example query term with trailing wildcard + * query.term('foo', { wildcard: lunr.Query.wildcard.TRAILING }) + * @example query term with leading and trailing wildcard + * query.term('foo', { + * wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING + * }) + */ + +lunr.Query.wildcard = new String ("*") +lunr.Query.wildcard.NONE = 0 +lunr.Query.wildcard.LEADING = 1 +lunr.Query.wildcard.TRAILING = 2 + +/** + * Constants for indicating what kind of presence a term must have in matching documents. + * + * @constant + * @enum {number} + * @see lunr.Query~Clause + * @see lunr.Query#clause + * @see lunr.Query#term + * @example query term with required presence + * query.term('foo', { presence: lunr.Query.presence.REQUIRED }) + */ +lunr.Query.presence = { + /** + * Term's presence in a document is optional, this is the default value. + */ + OPTIONAL: 1, + + /** + * Term's presence in a document is required, documents that do not contain + * this term will not be returned. + */ + REQUIRED: 2, + + /** + * Term's presence in a document is prohibited, documents that do contain + * this term will not be returned. + */ + PROHIBITED: 3 +} + +/** + * A single clause in a {@link lunr.Query} contains a term and details on how to + * match that term against a {@link lunr.Index}. + * + * @typedef {Object} lunr.Query~Clause + * @property {string[]} fields - The fields in an index this clause should be matched against. + * @property {number} [boost=1] - Any boost that should be applied when matching this clause. + * @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be. + * @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline. + * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended. + * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents. + */ + +/** + * Adds a {@link lunr.Query~Clause} to this query. + * + * Unless the clause contains the fields to be matched all fields will be matched. In addition + * a default boost of 1 is applied to the clause. + * + * @param {lunr.Query~Clause} clause - The clause to add to this query. + * @see lunr.Query~Clause + * @returns {lunr.Query} + */ +lunr.Query.prototype.clause = function (clause) { + if (!('fields' in clause)) { + clause.fields = this.allFields + } + + if (!('boost' in clause)) { + clause.boost = 1 + } + + if (!('usePipeline' in clause)) { + clause.usePipeline = true + } + + if (!('wildcard' in clause)) { + clause.wildcard = lunr.Query.wildcard.NONE + } + + if ((clause.wildcard & lunr.Query.wildcard.LEADING) && (clause.term.charAt(0) != lunr.Query.wildcard)) { + clause.term = "*" + clause.term + } + + if ((clause.wildcard & lunr.Query.wildcard.TRAILING) && (clause.term.slice(-1) != lunr.Query.wildcard)) { + clause.term = "" + clause.term + "*" + } + + if (!('presence' in clause)) { + clause.presence = lunr.Query.presence.OPTIONAL + } + + this.clauses.push(clause) + + return this +} + +/** + * A negated query is one in which every clause has a presence of + * prohibited. These queries require some special processing to return + * the expected results. + * + * @returns boolean + */ +lunr.Query.prototype.isNegated = function () { + for (var i = 0; i < this.clauses.length; i++) { + if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) { + return false + } + } + + return true +} + +/** + * Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause} + * to the list of clauses that make up this query. + * + * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion + * to a token or token-like string should be done before calling this method. + * + * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an + * array, each term in the array will share the same options. + * + * @param {object|object[]} term - The term(s) to add to the query. + * @param {object} [options] - Any additional properties to add to the query clause. + * @returns {lunr.Query} + * @see lunr.Query#clause + * @see lunr.Query~Clause + * @example adding a single term to a query + * query.term("foo") + * @example adding a single term to a query and specifying search fields, term boost and automatic trailing wildcard + * query.term("foo", { + * fields: ["title"], + * boost: 10, + * wildcard: lunr.Query.wildcard.TRAILING + * }) + * @example using lunr.tokenizer to convert a string to tokens before using them as terms + * query.term(lunr.tokenizer("foo bar")) + */ +lunr.Query.prototype.term = function (term, options) { + if (Array.isArray(term)) { + term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this) + return this + } + + var clause = options || {} + clause.term = term.toString() + + this.clause(clause) + + return this +} +lunr.QueryParseError = function (message, start, end) { + this.name = "QueryParseError" + this.message = message + this.start = start + this.end = end +} + +lunr.QueryParseError.prototype = new Error +lunr.QueryLexer = function (str) { + this.lexemes = [] + this.str = str + this.length = str.length + this.pos = 0 + this.start = 0 + this.escapeCharPositions = [] +} + +lunr.QueryLexer.prototype.run = function () { + var state = lunr.QueryLexer.lexText + + while (state) { + state = state(this) + } +} + +lunr.QueryLexer.prototype.sliceString = function () { + var subSlices = [], + sliceStart = this.start, + sliceEnd = this.pos + + for (var i = 0; i < this.escapeCharPositions.length; i++) { + sliceEnd = this.escapeCharPositions[i] + subSlices.push(this.str.slice(sliceStart, sliceEnd)) + sliceStart = sliceEnd + 1 + } + + subSlices.push(this.str.slice(sliceStart, this.pos)) + this.escapeCharPositions.length = 0 + + return subSlices.join('') +} + +lunr.QueryLexer.prototype.emit = function (type) { + this.lexemes.push({ + type: type, + str: this.sliceString(), + start: this.start, + end: this.pos + }) + + this.start = this.pos +} + +lunr.QueryLexer.prototype.escapeCharacter = function () { + this.escapeCharPositions.push(this.pos - 1) + this.pos += 1 +} + +lunr.QueryLexer.prototype.next = function () { + if (this.pos >= this.length) { + return lunr.QueryLexer.EOS + } + + var char = this.str.charAt(this.pos) + this.pos += 1 + return char +} + +lunr.QueryLexer.prototype.width = function () { + return this.pos - this.start +} + +lunr.QueryLexer.prototype.ignore = function () { + if (this.start == this.pos) { + this.pos += 1 + } + + this.start = this.pos +} + +lunr.QueryLexer.prototype.backup = function () { + this.pos -= 1 +} + +lunr.QueryLexer.prototype.acceptDigitRun = function () { + var char, charCode + + do { + char = this.next() + charCode = char.charCodeAt(0) + } while (charCode > 47 && charCode < 58) + + if (char != lunr.QueryLexer.EOS) { + this.backup() + } +} + +lunr.QueryLexer.prototype.more = function () { + return this.pos < this.length +} + +lunr.QueryLexer.EOS = 'EOS' +lunr.QueryLexer.FIELD = 'FIELD' +lunr.QueryLexer.TERM = 'TERM' +lunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE' +lunr.QueryLexer.BOOST = 'BOOST' +lunr.QueryLexer.PRESENCE = 'PRESENCE' + +lunr.QueryLexer.lexField = function (lexer) { + lexer.backup() + lexer.emit(lunr.QueryLexer.FIELD) + lexer.ignore() + return lunr.QueryLexer.lexText +} + +lunr.QueryLexer.lexTerm = function (lexer) { + if (lexer.width() > 1) { + lexer.backup() + lexer.emit(lunr.QueryLexer.TERM) + } + + lexer.ignore() + + if (lexer.more()) { + return lunr.QueryLexer.lexText + } +} + +lunr.QueryLexer.lexEditDistance = function (lexer) { + lexer.ignore() + lexer.acceptDigitRun() + lexer.emit(lunr.QueryLexer.EDIT_DISTANCE) + return lunr.QueryLexer.lexText +} + +lunr.QueryLexer.lexBoost = function (lexer) { + lexer.ignore() + lexer.acceptDigitRun() + lexer.emit(lunr.QueryLexer.BOOST) + return lunr.QueryLexer.lexText +} + +lunr.QueryLexer.lexEOS = function (lexer) { + if (lexer.width() > 0) { + lexer.emit(lunr.QueryLexer.TERM) + } +} + +// This matches the separator used when tokenising fields +// within a document. These should match otherwise it is +// not possible to search for some tokens within a document. +// +// It is possible for the user to change the separator on the +// tokenizer so it _might_ clash with any other of the special +// characters already used within the search string, e.g. :. +// +// This means that it is possible to change the separator in +// such a way that makes some words unsearchable using a search +// string. +lunr.QueryLexer.termSeparator = lunr.tokenizer.separator + +lunr.QueryLexer.lexText = function (lexer) { + while (true) { + var char = lexer.next() + + if (char == lunr.QueryLexer.EOS) { + return lunr.QueryLexer.lexEOS + } + + // Escape character is '\' + if (char.charCodeAt(0) == 92) { + lexer.escapeCharacter() + continue + } + + if (char == ":") { + return lunr.QueryLexer.lexField + } + + if (char == "~") { + lexer.backup() + if (lexer.width() > 0) { + lexer.emit(lunr.QueryLexer.TERM) + } + return lunr.QueryLexer.lexEditDistance + } + + if (char == "^") { + lexer.backup() + if (lexer.width() > 0) { + lexer.emit(lunr.QueryLexer.TERM) + } + return lunr.QueryLexer.lexBoost + } + + // "+" indicates term presence is required + // checking for length to ensure that only + // leading "+" are considered + if (char == "+" && lexer.width() === 1) { + lexer.emit(lunr.QueryLexer.PRESENCE) + return lunr.QueryLexer.lexText + } + + // "-" indicates term presence is prohibited + // checking for length to ensure that only + // leading "-" are considered + if (char == "-" && lexer.width() === 1) { + lexer.emit(lunr.QueryLexer.PRESENCE) + return lunr.QueryLexer.lexText + } + + if (char.match(lunr.QueryLexer.termSeparator)) { + return lunr.QueryLexer.lexTerm + } + } +} + +lunr.QueryParser = function (str, query) { + this.lexer = new lunr.QueryLexer (str) + this.query = query + this.currentClause = {} + this.lexemeIdx = 0 +} + +lunr.QueryParser.prototype.parse = function () { + this.lexer.run() + this.lexemes = this.lexer.lexemes + + var state = lunr.QueryParser.parseClause + + while (state) { + state = state(this) + } + + return this.query +} + +lunr.QueryParser.prototype.peekLexeme = function () { + return this.lexemes[this.lexemeIdx] +} + +lunr.QueryParser.prototype.consumeLexeme = function () { + var lexeme = this.peekLexeme() + this.lexemeIdx += 1 + return lexeme +} + +lunr.QueryParser.prototype.nextClause = function () { + var completedClause = this.currentClause + this.query.clause(completedClause) + this.currentClause = {} +} + +lunr.QueryParser.parseClause = function (parser) { + var lexeme = parser.peekLexeme() + + if (lexeme == undefined) { + return + } + + switch (lexeme.type) { + case lunr.QueryLexer.PRESENCE: + return lunr.QueryParser.parsePresence + case lunr.QueryLexer.FIELD: + return lunr.QueryParser.parseField + case lunr.QueryLexer.TERM: + return lunr.QueryParser.parseTerm + default: + var errorMessage = "expected either a field or a term, found " + lexeme.type + + if (lexeme.str.length >= 1) { + errorMessage += " with value '" + lexeme.str + "'" + } + + throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) + } +} + +lunr.QueryParser.parsePresence = function (parser) { + var lexeme = parser.consumeLexeme() + + if (lexeme == undefined) { + return + } + + switch (lexeme.str) { + case "-": + parser.currentClause.presence = lunr.Query.presence.PROHIBITED + break + case "+": + parser.currentClause.presence = lunr.Query.presence.REQUIRED + break + default: + var errorMessage = "unrecognised presence operator'" + lexeme.str + "'" + throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) + } + + var nextLexeme = parser.peekLexeme() + + if (nextLexeme == undefined) { + var errorMessage = "expecting term or field, found nothing" + throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) + } + + switch (nextLexeme.type) { + case lunr.QueryLexer.FIELD: + return lunr.QueryParser.parseField + case lunr.QueryLexer.TERM: + return lunr.QueryParser.parseTerm + default: + var errorMessage = "expecting term or field, found '" + nextLexeme.type + "'" + throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) + } +} + +lunr.QueryParser.parseField = function (parser) { + var lexeme = parser.consumeLexeme() + + if (lexeme == undefined) { + return + } + + if (parser.query.allFields.indexOf(lexeme.str) == -1) { + var possibleFields = parser.query.allFields.map(function (f) { return "'" + f + "'" }).join(', '), + errorMessage = "unrecognised field '" + lexeme.str + "', possible fields: " + possibleFields + + throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) + } + + parser.currentClause.fields = [lexeme.str] + + var nextLexeme = parser.peekLexeme() + + if (nextLexeme == undefined) { + var errorMessage = "expecting term, found nothing" + throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) + } + + switch (nextLexeme.type) { + case lunr.QueryLexer.TERM: + return lunr.QueryParser.parseTerm + default: + var errorMessage = "expecting term, found '" + nextLexeme.type + "'" + throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) + } +} + +lunr.QueryParser.parseTerm = function (parser) { + var lexeme = parser.consumeLexeme() + + if (lexeme == undefined) { + return + } + + parser.currentClause.term = lexeme.str.toLowerCase() + + if (lexeme.str.indexOf("*") != -1) { + parser.currentClause.usePipeline = false + } + + var nextLexeme = parser.peekLexeme() + + if (nextLexeme == undefined) { + parser.nextClause() + return + } + + switch (nextLexeme.type) { + case lunr.QueryLexer.TERM: + parser.nextClause() + return lunr.QueryParser.parseTerm + case lunr.QueryLexer.FIELD: + parser.nextClause() + return lunr.QueryParser.parseField + case lunr.QueryLexer.EDIT_DISTANCE: + return lunr.QueryParser.parseEditDistance + case lunr.QueryLexer.BOOST: + return lunr.QueryParser.parseBoost + case lunr.QueryLexer.PRESENCE: + parser.nextClause() + return lunr.QueryParser.parsePresence + default: + var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'" + throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) + } +} + +lunr.QueryParser.parseEditDistance = function (parser) { + var lexeme = parser.consumeLexeme() + + if (lexeme == undefined) { + return + } + + var editDistance = parseInt(lexeme.str, 10) + + if (isNaN(editDistance)) { + var errorMessage = "edit distance must be numeric" + throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) + } + + parser.currentClause.editDistance = editDistance + + var nextLexeme = parser.peekLexeme() + + if (nextLexeme == undefined) { + parser.nextClause() + return + } + + switch (nextLexeme.type) { + case lunr.QueryLexer.TERM: + parser.nextClause() + return lunr.QueryParser.parseTerm + case lunr.QueryLexer.FIELD: + parser.nextClause() + return lunr.QueryParser.parseField + case lunr.QueryLexer.EDIT_DISTANCE: + return lunr.QueryParser.parseEditDistance + case lunr.QueryLexer.BOOST: + return lunr.QueryParser.parseBoost + case lunr.QueryLexer.PRESENCE: + parser.nextClause() + return lunr.QueryParser.parsePresence + default: + var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'" + throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) + } +} + +lunr.QueryParser.parseBoost = function (parser) { + var lexeme = parser.consumeLexeme() + + if (lexeme == undefined) { + return + } + + var boost = parseInt(lexeme.str, 10) + + if (isNaN(boost)) { + var errorMessage = "boost must be numeric" + throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end) + } + + parser.currentClause.boost = boost + + var nextLexeme = parser.peekLexeme() + + if (nextLexeme == undefined) { + parser.nextClause() + return + } + + switch (nextLexeme.type) { + case lunr.QueryLexer.TERM: + parser.nextClause() + return lunr.QueryParser.parseTerm + case lunr.QueryLexer.FIELD: + parser.nextClause() + return lunr.QueryParser.parseField + case lunr.QueryLexer.EDIT_DISTANCE: + return lunr.QueryParser.parseEditDistance + case lunr.QueryLexer.BOOST: + return lunr.QueryParser.parseBoost + case lunr.QueryLexer.PRESENCE: + parser.nextClause() + return lunr.QueryParser.parsePresence + default: + var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'" + throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end) + } +} + + /** + * export the module via AMD, CommonJS or as a browser global + * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js + */ + ;(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(factory) + } else if (typeof exports === 'object') { + /** + * Node. Does not work with strict CommonJS, but + * only CommonJS-like environments that support module.exports, + * like Node. + */ + module.exports = factory() + } else { + // Browser globals (root is window) + root.lunr = factory() + } + }(this, function () { + /** + * Just return a value to define the module export. + * This example returns an object, but the module + * can return a function as the exported value. + */ + return lunr + })) +})(); diff --git a/search/main.js b/search/main.js new file mode 100755 index 0000000..a5e469d --- /dev/null +++ b/search/main.js @@ -0,0 +1,109 @@ +function getSearchTermFromLocation() { + var sPageURL = window.location.search.substring(1); + var sURLVariables = sPageURL.split('&'); + for (var i = 0; i < sURLVariables.length; i++) { + var sParameterName = sURLVariables[i].split('='); + if (sParameterName[0] == 'q') { + return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20')); + } + } +} + +function joinUrl (base, path) { + if (path.substring(0, 1) === "/") { + // path starts with `/`. Thus it is absolute. + return path; + } + if (base.substring(base.length-1) === "/") { + // base ends with `/` + return base + path; + } + return base + "/" + path; +} + +function escapeHtml (value) { + return value.replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>'); +} + +function formatResult (location, title, summary) { + return ''; +} + +function displayResults (results) { + var search_results = document.getElementById("mkdocs-search-results"); + while (search_results.firstChild) { + search_results.removeChild(search_results.firstChild); + } + if (results.length > 0){ + for (var i=0; i < results.length; i++){ + var result = results[i]; + var html = formatResult(result.location, result.title, result.summary); + search_results.insertAdjacentHTML('beforeend', html); + } + } else { + var noResultsText = search_results.getAttribute('data-no-results-text'); + if (!noResultsText) { + noResultsText = "No results found"; + } + search_results.insertAdjacentHTML('beforeend', '

' + noResultsText + '

'); + } +} + +function doSearch () { + var query = document.getElementById('mkdocs-search-query').value; + if (query.length > min_search_length) { + if (!window.Worker) { + displayResults(search(query)); + } else { + searchWorker.postMessage({query: query}); + } + } else { + // Clear results for short queries + displayResults([]); + } +} + +function initSearch () { + var search_input = document.getElementById('mkdocs-search-query'); + if (search_input) { + search_input.addEventListener("keyup", doSearch); + } + var term = getSearchTermFromLocation(); + if (term) { + search_input.value = term; + doSearch(); + } +} + +function onWorkerMessage (e) { + if (e.data.allowSearch) { + initSearch(); + } else if (e.data.results) { + var results = e.data.results; + displayResults(results); + } else if (e.data.config) { + min_search_length = e.data.config.min_search_length-1; + } +} + +if (!window.Worker) { + console.log('Web Worker API not supported'); + // load index in main thread + $.getScript(joinUrl(base_url, "search/worker.js")).done(function () { + console.log('Loaded worker'); + init(); + window.postMessage = function (msg) { + onWorkerMessage({data: msg}); + }; + }).fail(function (jqxhr, settings, exception) { + console.error('Could not load worker.js'); + }); +} else { + // Wrap search in a web worker + var searchWorker = new Worker(joinUrl(base_url, "search/worker.js")); + searchWorker.postMessage({init: true}); + searchWorker.onmessage = onWorkerMessage; +} diff --git a/search/search_index.json b/search/search_index.json new file mode 100755 index 0000000..725642d --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"EDK2Code Star The EDK2Code Extension for Visual Studio Code enhances the development experience for engineers working with the EDK2 (UEFI) codebase by providing features such as syntax highlighting, code navigation, and error detection. This extension integrates these capabilities directly into Visual Studio Code, enabling developers to streamline their workflow and increase productivity. By leveraging the EDK2Code extension, developers can easily navigate through code, quickly identify errors, and benefit from improved readability of EDK2 source files. This results in a more efficient development process and a smoother coding experience. Additionally, the extension supports various EDK2-specific commands accessible via the command palette, such as rebuilding the index database and configuring the workspace. This comprehensive toolset empowers developers to work more effectively with EDK2 projects, ultimately leading to higher quality code and faster development cycles. Check YouTube video presentation on UEFIForum Channel Github VSCODE","title":"EDK2Code"},{"location":"#edk2code","text":"Star The EDK2Code Extension for Visual Studio Code enhances the development experience for engineers working with the EDK2 (UEFI) codebase by providing features such as syntax highlighting, code navigation, and error detection. This extension integrates these capabilities directly into Visual Studio Code, enabling developers to streamline their workflow and increase productivity. By leveraging the EDK2Code extension, developers can easily navigate through code, quickly identify errors, and benefit from improved readability of EDK2 source files. This results in a more efficient development process and a smoother coding experience. Additionally, the extension supports various EDK2-specific commands accessible via the command palette, such as rebuilding the index database and configuring the workspace. This comprehensive toolset empowers developers to work more effectively with EDK2 projects, ultimately leading to higher quality code and faster development cycles. Check YouTube video presentation on UEFIForum Channel Github VSCODE","title":"EDK2Code"},{"location":"Index-source-code/","text":"Quick start Most of the extension functionality will work out of the box on any given EDK2 project. However it will have the full set of features enabled when the source code is compiled and the workspace is loaded. Loading the workspace When you open a folder that contains an EDK2 project, look for the Edk2Code icon in the activity bar on the left side of VS Code. Clicking it opens the Edk2Code sidebar, which contains the Workspace and Module Info views. The Workspace view will guide you through loading your build configuration. If nothing is loaded yet, you will see the welcome screen: Option 1 \u2014 Auto-discover build folders (recommended) If you have already compiled your EDK2 project, click Discover Build Folders . The extension will scan your workspace and detect all existing build output folders automatically. Once discovery completes, click Use discovered folders to load the detected configurations. The Workspace view will populate with your DSC, INF, and source file hierarchy. You can also trigger this at any time from the command palette : > EDK2: Discover build folders > EDK2: Use discovered build folders Option 2 \u2014 Manual configuration Click Open EDK2 Configuration (or run EDK2: Workspace configuration (UI) ) to open the settings panel and manually specify: DSC paths \u2014 the main .dsc files for your platform Build Defines \u2014 any -D flags used in your build command Package paths \u2014 extra package roots passed to the build > EDK2: Workspace configuration (UI) Rebuild / Rescan To force a full re-index after a new build, use: > EDK2: Rebuild index database To reload using the existing configuration without changing any settings: > EDK2: Rescan index database Enable compile information You can use the compile information build feature from EDK2 to provide more build information to the extension. This is optional but recommended To enable the compile information you need to enable the build report flag in the EDK2 build command and set -Y COMPILE_INFO . You can check more information about EDK build process here For example, if you want to build EmulatorPkg from EDK2 source, your build command will look like this: build -p EmulatorPkg\\EmulatorPkg.dsc -t VS2019 -a IA32 -Y COMPILE_INFO -y BuildReport.log This will generate compile information in your build folder. -Y COMPILE_INFO -y BuildReport.log will add to your build folder the CompileInfo folder: x:\\Edk2\\Build\\EmulatorIA32\\DEBUG_VS2019\\CompileInfo Files produced after parsing After parsing is completed, some files will be created in .edkCode folder on your workspace. .ignore This is a list of all your the files in your source that were not used during compilation. The generation of this file can be disabled in the extension settings. This file is used by VSCODE to ignore unused files. You can toggle the use of .ignore file in search: compile_commands.json This is the compilation database generated during build process. You can setup your C/C++ VSCODE plugging to use this compilation database to get better C parsing. To setup compile commands in your workspace, open C/C++: edit configurations (UI) in command palette. Under Advance Settings look for Compile commands property. Set the path for ${workspaceFolder}\\.edkCode\\compile_commands.json as shown in the following image: The EDK2Code extension will detect if compile_commands.json exists and will prompt the user to update the configuration cscope.files This is the list of all your files used in compilation. This file is used by Cscope to help provide C definitions.","title":"Quick start"},{"location":"Index-source-code/#quick-start","text":"Most of the extension functionality will work out of the box on any given EDK2 project. However it will have the full set of features enabled when the source code is compiled and the workspace is loaded.","title":"Quick start"},{"location":"Index-source-code/#loading-the-workspace","text":"When you open a folder that contains an EDK2 project, look for the Edk2Code icon in the activity bar on the left side of VS Code. Clicking it opens the Edk2Code sidebar, which contains the Workspace and Module Info views. The Workspace view will guide you through loading your build configuration. If nothing is loaded yet, you will see the welcome screen:","title":"Loading the workspace"},{"location":"Index-source-code/#option-1-auto-discover-build-folders-recommended","text":"If you have already compiled your EDK2 project, click Discover Build Folders . The extension will scan your workspace and detect all existing build output folders automatically. Once discovery completes, click Use discovered folders to load the detected configurations. The Workspace view will populate with your DSC, INF, and source file hierarchy. You can also trigger this at any time from the command palette : > EDK2: Discover build folders > EDK2: Use discovered build folders","title":"Option 1 \u2014 Auto-discover build folders (recommended)"},{"location":"Index-source-code/#option-2-manual-configuration","text":"Click Open EDK2 Configuration (or run EDK2: Workspace configuration (UI) ) to open the settings panel and manually specify: DSC paths \u2014 the main .dsc files for your platform Build Defines \u2014 any -D flags used in your build command Package paths \u2014 extra package roots passed to the build > EDK2: Workspace configuration (UI)","title":"Option 2 \u2014 Manual configuration"},{"location":"Index-source-code/#rebuild-rescan","text":"To force a full re-index after a new build, use: > EDK2: Rebuild index database To reload using the existing configuration without changing any settings: > EDK2: Rescan index database","title":"Rebuild / Rescan"},{"location":"Index-source-code/#enable-compile-information","text":"You can use the compile information build feature from EDK2 to provide more build information to the extension. This is optional but recommended To enable the compile information you need to enable the build report flag in the EDK2 build command and set -Y COMPILE_INFO . You can check more information about EDK build process here For example, if you want to build EmulatorPkg from EDK2 source, your build command will look like this: build -p EmulatorPkg\\EmulatorPkg.dsc -t VS2019 -a IA32 -Y COMPILE_INFO -y BuildReport.log This will generate compile information in your build folder. -Y COMPILE_INFO -y BuildReport.log will add to your build folder the CompileInfo folder: x:\\Edk2\\Build\\EmulatorIA32\\DEBUG_VS2019\\CompileInfo","title":"Enable compile information"},{"location":"Index-source-code/#files-produced-after-parsing","text":"After parsing is completed, some files will be created in .edkCode folder on your workspace.","title":"Files produced after parsing"},{"location":"Index-source-code/#ignore","text":"This is a list of all your the files in your source that were not used during compilation. The generation of this file can be disabled in the extension settings. This file is used by VSCODE to ignore unused files. You can toggle the use of .ignore file in search:","title":".ignore"},{"location":"Index-source-code/#compile_commandsjson","text":"This is the compilation database generated during build process. You can setup your C/C++ VSCODE plugging to use this compilation database to get better C parsing. To setup compile commands in your workspace, open C/C++: edit configurations (UI) in command palette. Under Advance Settings look for Compile commands property. Set the path for ${workspaceFolder}\\.edkCode\\compile_commands.json as shown in the following image: The EDK2Code extension will detect if compile_commands.json exists and will prompt the user to update the configuration","title":"compile_commands.json"},{"location":"Index-source-code/#cscopefiles","text":"This is the list of all your files used in compilation. This file is used by Cscope to help provide C definitions.","title":"cscope.files"},{"location":"requirements/","text":"Requirements Visual Studio Code ^1.77.0 Cscope Cscope is used for some C related functionality of the extension. On windows systems the cscope comes already included in the extension. For linux systems you need to install cscope manually. Ubuntu installation example: sudo apt install cscope Additionally, you can use the vscode setting edk2code.cscopeOverwritePath to point cscope to your preferred installation path.","title":"Requirements"},{"location":"requirements/#requirements","text":"","title":"Requirements"},{"location":"requirements/#visual-studio-code-1770","text":"","title":"Visual Studio Code ^1.77.0"},{"location":"requirements/#cscope","text":"Cscope is used for some C related functionality of the extension. On windows systems the cscope comes already included in the extension. For linux systems you need to install cscope manually. Ubuntu installation example: sudo apt install cscope Additionally, you can use the vscode setting edk2code.cscopeOverwritePath to point cscope to your preferred installation path.","title":"Cscope"},{"location":"documentation/","text":"Index database","title":"Index database"},{"location":"documentation/#index-database","text":"","title":"Index database"},{"location":"documentation/Settings/","text":"Extension settings Edk2code: Log Level Used to debug the extension development. Its recommended to keep on None unless you are debugging the Edk2Code extension. Edk2code: Generate Ignore File Generates .ignore file as part of source index process Edk2code: Use Cscope Enable or disable cscope integration. When disabled, the cscope database will not be built or queried, and features that depend on it (call hierarchy, cscope-based Go to definition ) will be unavailable. A reload of VS Code is required after changing this setting. Edk2code: Mcp Server Port Port number used by the MCP SSE server started with EDK2: Start MCP SSE Server . Default: 3100 . Edk2code: Cscope Overwrite Path Overwrites the path used to invoke the cscope executable. Leave empty to use the one available on PATH . A reload of VS Code is required after changing this setting.","title":"Extension settings"},{"location":"documentation/Settings/#extension-settings","text":"","title":"Extension settings"},{"location":"documentation/Settings/#edk2code-log-level","text":"Used to debug the extension development. Its recommended to keep on None unless you are debugging the Edk2Code extension.","title":"Edk2code: Log Level"},{"location":"documentation/Settings/#edk2code-generate-ignore-file","text":"Generates .ignore file as part of source index process","title":"Edk2code: Generate Ignore File"},{"location":"documentation/Settings/#edk2code-use-cscope","text":"Enable or disable cscope integration. When disabled, the cscope database will not be built or queried, and features that depend on it (call hierarchy, cscope-based Go to definition ) will be unavailable. A reload of VS Code is required after changing this setting.","title":"Edk2code: Use Cscope"},{"location":"documentation/Settings/#edk2code-mcp-server-port","text":"Port number used by the MCP SSE server started with EDK2: Start MCP SSE Server . Default: 3100 .","title":"Edk2code: Mcp Server Port"},{"location":"documentation/Settings/#edk2code-cscope-overwrite-path","text":"Overwrites the path used to invoke the cscope executable. Leave empty to use the one available on PATH . A reload of VS Code is required after changing this setting.","title":"Edk2code: Cscope Overwrite Path"},{"location":"documentation/Workspace-settings/","text":"Workspace settings The workspace configuration controls which DSC files, build defines, and package paths the extension uses when parsing your EDK2 project. Configuration UI The easiest way to manage the workspace settings is through the graphical configuration panel. Open it from the Workspace view title bar ( $(gear) icon) or via the command palette: > EDK2: Workspace configuration (UI) The panel lets you set: DSC paths \u2014 the main .dsc files for your platform (relative to the workspace root). Build Defines \u2014 definitions injected in your build command with -D (e.g. ARCH=X64 ). Package paths \u2014 additional package roots passed to the EDK2 build. Configuration file The settings are stored in .edkCode/edk2_workspace_properties.json inside your workspace. You can also edit this file directly or open it with: > EDK2: Workspace configuration (JSON) { \"packagePaths\": [], \"dscPaths\": [ \"OvmfPkg\\\\OvmfPkgX64.dsc\" ], \"buildDefines\": [ \"ARCH=X64\" ] } dscPaths \u2014 Each entry should be a main DSC file used for compilation. buildDefines \u2014 Definitions injected in your build command with -D . Add or modify entries to match your build. After any modification to this file, VS Code will prompt you to reload the index.","title":"Workspace settings"},{"location":"documentation/Workspace-settings/#workspace-settings","text":"The workspace configuration controls which DSC files, build defines, and package paths the extension uses when parsing your EDK2 project.","title":"Workspace settings"},{"location":"documentation/Workspace-settings/#configuration-ui","text":"The easiest way to manage the workspace settings is through the graphical configuration panel. Open it from the Workspace view title bar ( $(gear) icon) or via the command palette: > EDK2: Workspace configuration (UI) The panel lets you set: DSC paths \u2014 the main .dsc files for your platform (relative to the workspace root). Build Defines \u2014 definitions injected in your build command with -D (e.g. ARCH=X64 ). Package paths \u2014 additional package roots passed to the EDK2 build.","title":"Configuration UI"},{"location":"documentation/Workspace-settings/#configuration-file","text":"The settings are stored in .edkCode/edk2_workspace_properties.json inside your workspace. You can also edit this file directly or open it with: > EDK2: Workspace configuration (JSON) { \"packagePaths\": [], \"dscPaths\": [ \"OvmfPkg\\\\OvmfPkgX64.dsc\" ], \"buildDefines\": [ \"ARCH=X64\" ] } dscPaths \u2014 Each entry should be a main DSC file used for compilation. buildDefines \u2014 Definitions injected in your build command with -D . Add or modify entries to match your build. After any modification to this file, VS Code will prompt you to reload the index.","title":"Configuration file"},{"location":"documentation/documentation/","text":"Documentation Before you start testing the functionality of the extension, please index your source code . Configuration You can check your workspace configuration with command: > EDK2: Workspace configuration (UI) This configuration will be automatically populated after you indexed your source code . DSC relative path Are the main DSC files for your workspace Build Defines Build defines that were injected in your EDK2 build command Package paths are the paths set for the EDK2 Build command. You can manually change this configuration. After any manual modification the user will be prompted to rescan the Index. Interface Status bar When you open a file in the editor, you will see in the status bar a warning if the file you are looking has been compiled or not: The following commands are expected to work only on files that have been used in compilation. Global commands This commands are only accessible using the command palette (\u2328F1) EDK2: Open library Will show a list of all the libraries compiled. EDK2: Open Module Will show a list of all the modules compiled. EDK2: Rebuild index database This will clean up the current source index and will create a new one. See Quick start for details. EDK2: Rescan index database This will use the previous index configuration and will recreate the index without changing the workspace settings EDK2 language support After you source code has been indexed you will see some of the features of using Edk2Code extension \u26a0 IMPORTANT Before continuing please index your code following this instructions INF files Inf files will show syntax highlight: Outline tree Source goto definition Right click on a source file name and then select Go To Definition (F12) This will open the source file selected. This also works for LibraryClasses , Pcd and Packages : The results shown are based on your DSC parsing. LibraryClasses Auto completion Start typing on the LibraryClasses section will show suggestions of libraries that can be included in that INF file: This suggestions are based on DEC files in Packages section. Goto DSC Declaration Right click on an anywhere in an INF file and select EDK2: Goto DSC Declaration This will open the DSC file where this INF file was declared. Library usage If the INF file is a library, right click and select EDK2: Show Library usage : This will show what modules are using your library: DSC Files Syntax highlight DSC files have full syntax highlighting for sections, conditionals ( !if , !else , !endif ), includes ( !include ), macros, PCDs, and module entries. Outline The Outline view shows all sections ( [LibraryClasses] , [Components] , [PcdsFixedAtBuild] , etc.) and their entries, allowing quick navigation within large DSC files. Variable defines resolution DSC files will dim source that hasn't been compiled based on DEFINES. You can see the value of the defines if you hover your mouse over. This also works with PCD values Goto Definition Right click on a file path and select Go to Definition (F12) to open that file. Goto DSC inclusion Right click and select Go to DSC Inclusion to see if this DSC file was included ( !Include ) in other DSC file. DEC Syntax highlight DEC files have syntax highlighting for section headers, GUID definitions, PCD declarations, library class definitions, and include paths. Outline The Outline view shows all sections ( [Guids] , [Protocols] , [Ppis] , [LibraryClasses] , [Pcds*] , etc.) for easy navigation. C files Call Hierarchy Right on a function name and select Show Call Hierarchy : This will open the References view with the call Hierarchy of the selected function. Edk2Code extension will filter unused calls from the view. Go to INF When you are on a C file, Right click and select Go to INF : This will open the .inf file that compiled that C file. Go to Definition Right click on a C symbol (function, variable, etc) and select EDK2: Go To Definition to open the symbol definition. This differs from regular Go to Definition command provided by VSCODE as this will uses CSCOPE and compiled files to query the definitions. Sometimes it gives better results. VFR Syntax highlight VFR (Visual Forms Representation) files have syntax highlighting for form definitions, questions, one-of selections, checkboxes, strings, and other HII form elements. Outline The Outline view shows the form set, individual forms, and their question elements, making it easy to navigate complex VFR layouts. ACPI Syntax highlight ASL (ACPI Source Language) files have syntax highlighting for device definitions, methods, operators, named objects, and resource descriptors. Outline The Outline view shows the ASL definition block structure including devices, methods, scopes, and named objects for easy navigation. Help Hover on keywords of your ASL code and you will see help extracted from ACPI specification (6.3) Auto complete Start typing anywhere in your *.asl files and you will see autocomplete suggestions of ASL specification. Edk2Code sidebar Starting in version 2.0.0 , the extension installs its own activity bar container. All Edk2Code views are grouped under this entry, which exposes two views: Workspace and Module Info . Workspace view The Workspace view shows your parsed EDK2 workspace as a single, persistent tree. It replaces the older Module Map , Library Tree and Reference Tree commands with one navigable hierarchy of DSC \u2192 INF \u2192 libraries / sources / headers. When no workspace is loaded yet, the welcome view offers quick actions to discover build folders or open the configuration UI. The view title bar exposes the following actions: Action Command Description $(gear) EDK2: Workspace configuration (UI) Open the graphical configuration panel. $(repo) EDK2: Select Workspace Switch between loaded build configurations. $(target) EDK2: Reveal active editor in workspace tree Locate the active file in the tree. $(search) EDK2: Search workspace tree Find a node by name. $(filter) EDK2: Filter workspace symbols Hide grayed-out / inactive elements. $(copy) EDK2: Copy workspace tree Copy the tree (or a sub-tree) as text. $(refresh) EDK2: Refresh workspace config Reload the workspace configuration. $(close) EDK2: Unload workspace Clear the currently loaded configuration. Additional capabilities: Drag and drop to rearrange tree nodes. Right-click \u2192 Copy path on any node. Searching for symbols from the command palette will automatically switch to the workspace that owns the result. Module Info view The Module Info view shows EDK2 module information for the file currently open in the editor. As soon as you open a C, INF or related source file that belongs to a module, the view populates with: The owning INF and its DSC declaration Libraries linked to the module Quick navigation actions (go to definition, open file, go to DSC declaration) Double-click any entry to jump directly to the corresponding source location. Build folder auto-discovery EDK2Code can scan your workspace and detect existing build output folders automatically \u2014 you don't need to point the extension at them manually. EDK2: Discover build folders scans the workspace. EDK2: Use discovered build folders loads the detected folders as workspace configurations. The Workspace welcome view exposes both actions when nothing is loaded yet. Compile EDK2 file You can compile an individual EDK2 C file directly from the editor without running a full EDK2 build: A play ( $(play) ) icon is shown in the editor title bar on supported source files. The command EDK2: Compile Edk2 file invokes the compiler for the active .c file using the flags and include paths recorded in compile_commands.json . \u26a0 NOTE This compiles the single C file in isolation \u2014 it runs outside the regular EDK2 build system and does not link or produce a final binary. It is intended as a fast feedback loop to catch syntax and type errors in a single translation unit without waiting for a full platform build. \u26a0 REQUIREMENT This feature requires a compile_commands.json to be present in your workspace. This file is generated automatically when you enable compile information during your EDK2 build using the -Y COMPILE_INFO flag. Goto overwriting definition When a symbol is overwritten in a DSC (libraries, PCDs, modules), a new code action lets you jump to the overwriting definition instead of the original. MCP server EDK2Code can expose a Model Context Protocol (MCP) SSE server so AI agents and tools (such as GitHub Copilot or other MCP-compatible clients) can query your parsed EDK2 workspace directly. Starting and stopping Open the Workspace configuration (UI) panel ( EDK2: Workspace configuration (UI) ) and use the Start MCP Server / Stop MCP Server button in the MCP section, or run the commands from the palette: > EDK2: Start MCP SSE Server > EDK2: Stop MCP SSE Server The edk2code.mcpServerPort setting controls the listening port (default 3100 ). Auto-configure workspace MCP To let VS Code and GitHub Copilot discover the server automatically, click Auto-configure workspace MCP in the Settings UI. This writes (or updates) the edk2code server entry in your workspace's .vscode/mcp.json file: { \"servers\": { \"edk2code\": { \"type\": \"sse\", \"url\": \"http://localhost:3100/sse\" } } } Once this file exists, VS Code will list the edk2code server under MCP Servers in Copilot Chat and any other MCP-compatible client. See the VS Code MCP documentation for more details on how MCP servers work.","title":"Documentation"},{"location":"documentation/documentation/#documentation","text":"Before you start testing the functionality of the extension, please index your source code .","title":"Documentation"},{"location":"documentation/documentation/#configuration","text":"You can check your workspace configuration with command: > EDK2: Workspace configuration (UI) This configuration will be automatically populated after you indexed your source code . DSC relative path Are the main DSC files for your workspace Build Defines Build defines that were injected in your EDK2 build command Package paths are the paths set for the EDK2 Build command. You can manually change this configuration. After any manual modification the user will be prompted to rescan the Index.","title":"Configuration"},{"location":"documentation/documentation/#interface","text":"","title":"Interface"},{"location":"documentation/documentation/#status-bar","text":"When you open a file in the editor, you will see in the status bar a warning if the file you are looking has been compiled or not: The following commands are expected to work only on files that have been used in compilation.","title":"Status bar"},{"location":"documentation/documentation/#global-commands","text":"This commands are only accessible using the command palette (\u2328F1)","title":"Global commands"},{"location":"documentation/documentation/#edk2-open-library","text":"Will show a list of all the libraries compiled.","title":"EDK2: Open library"},{"location":"documentation/documentation/#edk2-open-module","text":"Will show a list of all the modules compiled.","title":"EDK2: Open Module"},{"location":"documentation/documentation/#edk2-rebuild-index-database","text":"This will clean up the current source index and will create a new one. See Quick start for details.","title":"EDK2: Rebuild index database"},{"location":"documentation/documentation/#edk2-rescan-index-database","text":"This will use the previous index configuration and will recreate the index without changing the workspace settings","title":"EDK2: Rescan index database"},{"location":"documentation/documentation/#edk2-language-support","text":"After you source code has been indexed you will see some of the features of using Edk2Code extension \u26a0 IMPORTANT Before continuing please index your code following this instructions","title":"EDK2 language support"},{"location":"documentation/documentation/#inf-files","text":"","title":"INF files"},{"location":"documentation/documentation/#inf-files-will-show-syntax-highlight","text":"","title":"Inf files will show syntax highlight:"},{"location":"documentation/documentation/#outline-tree","text":"","title":"Outline tree"},{"location":"documentation/documentation/#source-goto-definition","text":"Right click on a source file name and then select Go To Definition (F12) This will open the source file selected. This also works for LibraryClasses , Pcd and Packages : The results shown are based on your DSC parsing.","title":"Source goto definition"},{"location":"documentation/documentation/#libraryclasses-auto-completion","text":"Start typing on the LibraryClasses section will show suggestions of libraries that can be included in that INF file: This suggestions are based on DEC files in Packages section.","title":"LibraryClasses Auto completion"},{"location":"documentation/documentation/#goto-dsc-declaration","text":"Right click on an anywhere in an INF file and select EDK2: Goto DSC Declaration This will open the DSC file where this INF file was declared.","title":"Goto DSC Declaration"},{"location":"documentation/documentation/#library-usage","text":"If the INF file is a library, right click and select EDK2: Show Library usage : This will show what modules are using your library:","title":"Library usage"},{"location":"documentation/documentation/#dsc-files","text":"","title":"DSC Files"},{"location":"documentation/documentation/#syntax-highlight","text":"DSC files have full syntax highlighting for sections, conditionals ( !if , !else , !endif ), includes ( !include ), macros, PCDs, and module entries.","title":"Syntax highlight"},{"location":"documentation/documentation/#outline","text":"The Outline view shows all sections ( [LibraryClasses] , [Components] , [PcdsFixedAtBuild] , etc.) and their entries, allowing quick navigation within large DSC files.","title":"Outline"},{"location":"documentation/documentation/#variable-defines-resolution","text":"DSC files will dim source that hasn't been compiled based on DEFINES. You can see the value of the defines if you hover your mouse over. This also works with PCD values","title":"Variable defines resolution"},{"location":"documentation/documentation/#goto-definition","text":"Right click on a file path and select Go to Definition (F12) to open that file.","title":"Goto Definition"},{"location":"documentation/documentation/#goto-dsc-inclusion","text":"Right click and select Go to DSC Inclusion to see if this DSC file was included ( !Include ) in other DSC file.","title":"Goto DSC inclusion"},{"location":"documentation/documentation/#dec","text":"","title":"DEC"},{"location":"documentation/documentation/#syntax-highlight_1","text":"DEC files have syntax highlighting for section headers, GUID definitions, PCD declarations, library class definitions, and include paths.","title":"Syntax highlight"},{"location":"documentation/documentation/#outline_1","text":"The Outline view shows all sections ( [Guids] , [Protocols] , [Ppis] , [LibraryClasses] , [Pcds*] , etc.) for easy navigation.","title":"Outline"},{"location":"documentation/documentation/#c-files","text":"","title":"C files"},{"location":"documentation/documentation/#call-hierarchy","text":"Right on a function name and select Show Call Hierarchy : This will open the References view with the call Hierarchy of the selected function. Edk2Code extension will filter unused calls from the view.","title":"Call Hierarchy"},{"location":"documentation/documentation/#go-to-inf","text":"When you are on a C file, Right click and select Go to INF : This will open the .inf file that compiled that C file.","title":"Go to INF"},{"location":"documentation/documentation/#go-to-definition","text":"Right click on a C symbol (function, variable, etc) and select EDK2: Go To Definition to open the symbol definition. This differs from regular Go to Definition command provided by VSCODE as this will uses CSCOPE and compiled files to query the definitions. Sometimes it gives better results.","title":"Go to Definition"},{"location":"documentation/documentation/#vfr","text":"","title":"VFR"},{"location":"documentation/documentation/#syntax-highlight_2","text":"VFR (Visual Forms Representation) files have syntax highlighting for form definitions, questions, one-of selections, checkboxes, strings, and other HII form elements.","title":"Syntax highlight"},{"location":"documentation/documentation/#outline_2","text":"The Outline view shows the form set, individual forms, and their question elements, making it easy to navigate complex VFR layouts.","title":"Outline"},{"location":"documentation/documentation/#acpi","text":"","title":"ACPI"},{"location":"documentation/documentation/#syntax-highlight_3","text":"ASL (ACPI Source Language) files have syntax highlighting for device definitions, methods, operators, named objects, and resource descriptors.","title":"Syntax highlight"},{"location":"documentation/documentation/#outline_3","text":"The Outline view shows the ASL definition block structure including devices, methods, scopes, and named objects for easy navigation.","title":"Outline"},{"location":"documentation/documentation/#help","text":"Hover on keywords of your ASL code and you will see help extracted from ACPI specification (6.3)","title":"Help"},{"location":"documentation/documentation/#auto-complete","text":"Start typing anywhere in your *.asl files and you will see autocomplete suggestions of ASL specification.","title":"Auto complete"},{"location":"documentation/documentation/#edk2code-sidebar","text":"Starting in version 2.0.0 , the extension installs its own activity bar container. All Edk2Code views are grouped under this entry, which exposes two views: Workspace and Module Info .","title":"Edk2Code sidebar"},{"location":"documentation/documentation/#workspace-view","text":"The Workspace view shows your parsed EDK2 workspace as a single, persistent tree. It replaces the older Module Map , Library Tree and Reference Tree commands with one navigable hierarchy of DSC \u2192 INF \u2192 libraries / sources / headers. When no workspace is loaded yet, the welcome view offers quick actions to discover build folders or open the configuration UI. The view title bar exposes the following actions: Action Command Description $(gear) EDK2: Workspace configuration (UI) Open the graphical configuration panel. $(repo) EDK2: Select Workspace Switch between loaded build configurations. $(target) EDK2: Reveal active editor in workspace tree Locate the active file in the tree. $(search) EDK2: Search workspace tree Find a node by name. $(filter) EDK2: Filter workspace symbols Hide grayed-out / inactive elements. $(copy) EDK2: Copy workspace tree Copy the tree (or a sub-tree) as text. $(refresh) EDK2: Refresh workspace config Reload the workspace configuration. $(close) EDK2: Unload workspace Clear the currently loaded configuration. Additional capabilities: Drag and drop to rearrange tree nodes. Right-click \u2192 Copy path on any node. Searching for symbols from the command palette will automatically switch to the workspace that owns the result.","title":"Workspace view"},{"location":"documentation/documentation/#module-info-view","text":"The Module Info view shows EDK2 module information for the file currently open in the editor. As soon as you open a C, INF or related source file that belongs to a module, the view populates with: The owning INF and its DSC declaration Libraries linked to the module Quick navigation actions (go to definition, open file, go to DSC declaration) Double-click any entry to jump directly to the corresponding source location.","title":"Module Info view"},{"location":"documentation/documentation/#build-folder-auto-discovery","text":"EDK2Code can scan your workspace and detect existing build output folders automatically \u2014 you don't need to point the extension at them manually. EDK2: Discover build folders scans the workspace. EDK2: Use discovered build folders loads the detected folders as workspace configurations. The Workspace welcome view exposes both actions when nothing is loaded yet.","title":"Build folder auto-discovery"},{"location":"documentation/documentation/#compile-edk2-file","text":"You can compile an individual EDK2 C file directly from the editor without running a full EDK2 build: A play ( $(play) ) icon is shown in the editor title bar on supported source files. The command EDK2: Compile Edk2 file invokes the compiler for the active .c file using the flags and include paths recorded in compile_commands.json . \u26a0 NOTE This compiles the single C file in isolation \u2014 it runs outside the regular EDK2 build system and does not link or produce a final binary. It is intended as a fast feedback loop to catch syntax and type errors in a single translation unit without waiting for a full platform build. \u26a0 REQUIREMENT This feature requires a compile_commands.json to be present in your workspace. This file is generated automatically when you enable compile information during your EDK2 build using the -Y COMPILE_INFO flag.","title":"Compile EDK2 file"},{"location":"documentation/documentation/#goto-overwriting-definition","text":"When a symbol is overwritten in a DSC (libraries, PCDs, modules), a new code action lets you jump to the overwriting definition instead of the original.","title":"Goto overwriting definition"},{"location":"documentation/documentation/#mcp-server","text":"EDK2Code can expose a Model Context Protocol (MCP) SSE server so AI agents and tools (such as GitHub Copilot or other MCP-compatible clients) can query your parsed EDK2 workspace directly.","title":"MCP server"},{"location":"documentation/documentation/#starting-and-stopping","text":"Open the Workspace configuration (UI) panel ( EDK2: Workspace configuration (UI) ) and use the Start MCP Server / Stop MCP Server button in the MCP section, or run the commands from the palette: > EDK2: Start MCP SSE Server > EDK2: Stop MCP SSE Server The edk2code.mcpServerPort setting controls the listening port (default 3100 ).","title":"Starting and stopping"},{"location":"documentation/documentation/#auto-configure-workspace-mcp","text":"To let VS Code and GitHub Copilot discover the server automatically, click Auto-configure workspace MCP in the Settings UI. This writes (or updates) the edk2code server entry in your workspace's .vscode/mcp.json file: { \"servers\": { \"edk2code\": { \"type\": \"sse\", \"url\": \"http://localhost:3100/sse\" } } } Once this file exists, VS Code will list the edk2code server under MCP Servers in Copilot Chat and any other MCP-compatible client. See the VS Code MCP documentation for more details on how MCP servers work.","title":"Auto-configure workspace MCP"},{"location":"releases/1.0.9/","text":"Thanks for using the Edk2Code Vscode extension. \ud83c\udf89 If you find this extension useful \ud83c\udf89: \u2b50 Give a start on Github \ud83d\udcdc Leave a review in Vscode marketplace 1.0.9 DSC analysis Shows problems in DSC files Module map Added context menu action Show Module Map . This action is available on INF files and will open EDK2 module map side panel to show: - Library tree - Source files tree (including Header files) You can also copy the path of the element selected in EDK2 module map using mouse context menu.","title":"1.0.9"},{"location":"releases/1.0.9/#109","text":"","title":"1.0.9"},{"location":"releases/1.0.9/#dsc-analysis","text":"Shows problems in DSC files","title":"DSC analysis"},{"location":"releases/1.0.9/#module-map","text":"Added context menu action Show Module Map . This action is available on INF files and will open EDK2 module map side panel to show: - Library tree - Source files tree (including Header files) You can also copy the path of the element selected in EDK2 module map using mouse context menu.","title":"Module map"},{"location":"releases/2.0.0/","text":"2.0.0 Edk2Code sidebar The extension now lives in a dedicated activity bar container . All Edk2Code views (Workspace, Module Info) are grouped together in the sidebar instead of being attached to the Explorer view. Workspace view The new Workspace view is a single, persistent tree representation of your parsed EDK2 workspace. It replaces the previous Module Map , Reference Tree and Library Tree commands. Key capabilities: Sub-trees and includes \u2014 DSC, INF, FDF and source files are organized hierarchically. Header includes and library sub-trees are integrated into the tree. Search \u2014 Click the $(search) action in the view title bar to find any node in the workspace tree. Filter inactive elements \u2014 Toggle the $(filter) action to hide grayed-out (inactive) items. Reveal active editor \u2014 The $(target) action jumps from the currently open file to its location in the workspace tree. Drag and drop \u2014 Reorganize nodes in the workspace tree directly with the mouse. Multiple workspaces \u2014 When multiple build configurations are loaded, switch between them from the $(repo) action in the title bar. Searching for symbols automatically switches to the workspace that owns the result. Copy node path / Copy tree \u2014 Quickly copy the path of a node, or export the entire tree as text via the $(copy) action. Welcome view \u2014 When no workspace is loaded, the view guides you through discovering build folders or opening the configuration UI. Module Info view The new Module Info view shows the EDK2 module information for the file you are currently editing. As soon as you open a C, INF or related source file that belongs to a module, the view populates with: The owning INF and its DSC declaration Libraries linked to the module Quick navigation actions (go to definition, open file, go to DSC declaration) Double-click any entry to jump directly to the corresponding source location. Build folder auto-discovery EDK2Code can now scan your workspace and automatically detect existing build output folders, so you don't have to point the extension at them manually. Run EDK2: Discover build folders to scan the workspace. Once discovered, run EDK2: Use discovered build folders to load them directly. The Workspace view welcome page surfaces these actions when nothing is loaded yet. Compile EDK2 file You can now compile an individual EDK2 file (e.g. a .c belonging to a module) directly from the editor. A play ( $(play) ) icon is shown in the editor title bar on supported source files. The command EDK2: Compile Edk2 file invokes the build for the parent module of the active file. MCP server integration EDK2Code now exposes an MCP (Model Context Protocol) SSE server that lets AI agents and external tools query your parsed EDK2 workspace. Start with EDK2: Start MCP SSE Server and stop with EDK2: Stop MCP SSE Server . Configure the listening port via the edk2code.mcpServerPort setting (default 3100 ). Settings UI A redesigned graphical Workspace configuration (UI) panel makes managing build configurations easier \u2014 no more hand-editing JSON for common setups. Launch from the Workspace view title bar ( $(gear) icon) or via the EDK2: Workspace configuration (UI) command. Goto overwriting definition When a symbol is overwritten in a DSC (libraries, PCDs, modules), a new code action lets you jump directly to the overwriting definition. Other improvements Disable cscope \u2014 A new edk2code.useCscope setting lets you turn off cscope integration entirely. When disabled, the cscope database is not built or queried (call hierarchy and cscope-based go-to-definition become unavailable). Unload workspace \u2014 New EDK2: Unload workspace command to clear the currently loaded build configuration. Refresh workspace config \u2014 Reload the workspace configuration without restarting VS Code. Focus INF from C files \u2014 Improved navigation from C source files back to their owning INF module. Better module symbols \u2014 DSC parser now recognizes module sub-context sections, build options, and provides improved symbols for libraries and modules. Loading and discovery indicators \u2014 Progress indicators are shown while the workspace is being parsed or build folders are being discovered. Improved grayout controller \u2014 Inactive code regions are computed and updated more reliably. Path improvements \u2014 Missing paths now report folders instead of file names, and tooltips include the full path. Extensive test suite \u2014 New parser and workspace tests covering ASL, DEC, DSC, FDF, INF and VFR.","title":"2.0.0"},{"location":"releases/2.0.0/#200","text":"","title":"2.0.0"},{"location":"releases/2.0.0/#edk2code-sidebar","text":"The extension now lives in a dedicated activity bar container . All Edk2Code views (Workspace, Module Info) are grouped together in the sidebar instead of being attached to the Explorer view.","title":"Edk2Code sidebar"},{"location":"releases/2.0.0/#workspace-view","text":"The new Workspace view is a single, persistent tree representation of your parsed EDK2 workspace. It replaces the previous Module Map , Reference Tree and Library Tree commands. Key capabilities: Sub-trees and includes \u2014 DSC, INF, FDF and source files are organized hierarchically. Header includes and library sub-trees are integrated into the tree. Search \u2014 Click the $(search) action in the view title bar to find any node in the workspace tree. Filter inactive elements \u2014 Toggle the $(filter) action to hide grayed-out (inactive) items. Reveal active editor \u2014 The $(target) action jumps from the currently open file to its location in the workspace tree. Drag and drop \u2014 Reorganize nodes in the workspace tree directly with the mouse. Multiple workspaces \u2014 When multiple build configurations are loaded, switch between them from the $(repo) action in the title bar. Searching for symbols automatically switches to the workspace that owns the result. Copy node path / Copy tree \u2014 Quickly copy the path of a node, or export the entire tree as text via the $(copy) action. Welcome view \u2014 When no workspace is loaded, the view guides you through discovering build folders or opening the configuration UI.","title":"Workspace view"},{"location":"releases/2.0.0/#module-info-view","text":"The new Module Info view shows the EDK2 module information for the file you are currently editing. As soon as you open a C, INF or related source file that belongs to a module, the view populates with: The owning INF and its DSC declaration Libraries linked to the module Quick navigation actions (go to definition, open file, go to DSC declaration) Double-click any entry to jump directly to the corresponding source location.","title":"Module Info view"},{"location":"releases/2.0.0/#build-folder-auto-discovery","text":"EDK2Code can now scan your workspace and automatically detect existing build output folders, so you don't have to point the extension at them manually. Run EDK2: Discover build folders to scan the workspace. Once discovered, run EDK2: Use discovered build folders to load them directly. The Workspace view welcome page surfaces these actions when nothing is loaded yet.","title":"Build folder auto-discovery"},{"location":"releases/2.0.0/#compile-edk2-file","text":"You can now compile an individual EDK2 file (e.g. a .c belonging to a module) directly from the editor. A play ( $(play) ) icon is shown in the editor title bar on supported source files. The command EDK2: Compile Edk2 file invokes the build for the parent module of the active file.","title":"Compile EDK2 file"},{"location":"releases/2.0.0/#mcp-server-integration","text":"EDK2Code now exposes an MCP (Model Context Protocol) SSE server that lets AI agents and external tools query your parsed EDK2 workspace. Start with EDK2: Start MCP SSE Server and stop with EDK2: Stop MCP SSE Server . Configure the listening port via the edk2code.mcpServerPort setting (default 3100 ).","title":"MCP server integration"},{"location":"releases/2.0.0/#settings-ui","text":"A redesigned graphical Workspace configuration (UI) panel makes managing build configurations easier \u2014 no more hand-editing JSON for common setups. Launch from the Workspace view title bar ( $(gear) icon) or via the EDK2: Workspace configuration (UI) command.","title":"Settings UI"},{"location":"releases/2.0.0/#goto-overwriting-definition","text":"When a symbol is overwritten in a DSC (libraries, PCDs, modules), a new code action lets you jump directly to the overwriting definition.","title":"Goto overwriting definition"},{"location":"releases/2.0.0/#other-improvements","text":"Disable cscope \u2014 A new edk2code.useCscope setting lets you turn off cscope integration entirely. When disabled, the cscope database is not built or queried (call hierarchy and cscope-based go-to-definition become unavailable). Unload workspace \u2014 New EDK2: Unload workspace command to clear the currently loaded build configuration. Refresh workspace config \u2014 Reload the workspace configuration without restarting VS Code. Focus INF from C files \u2014 Improved navigation from C source files back to their owning INF module. Better module symbols \u2014 DSC parser now recognizes module sub-context sections, build options, and provides improved symbols for libraries and modules. Loading and discovery indicators \u2014 Progress indicators are shown while the workspace is being parsed or build folders are being discovered. Improved grayout controller \u2014 Inactive code regions are computed and updated more reliably. Path improvements \u2014 Missing paths now report folders instead of file names, and tooltips include the full path. Extensive test suite \u2014 New parser and workspace tests covering ASL, DEC, DSC, FDF, INF and VFR.","title":"Other improvements"}]} \ No newline at end of file diff --git a/search/worker.js b/search/worker.js new file mode 100755 index 0000000..8628dbc --- /dev/null +++ b/search/worker.js @@ -0,0 +1,133 @@ +var base_path = 'function' === typeof importScripts ? '.' : '/search/'; +var allowSearch = false; +var index; +var documents = {}; +var lang = ['en']; +var data; + +function getScript(script, callback) { + console.log('Loading script: ' + script); + $.getScript(base_path + script).done(function () { + callback(); + }).fail(function (jqxhr, settings, exception) { + console.log('Error: ' + exception); + }); +} + +function getScriptsInOrder(scripts, callback) { + if (scripts.length === 0) { + callback(); + return; + } + getScript(scripts[0], function() { + getScriptsInOrder(scripts.slice(1), callback); + }); +} + +function loadScripts(urls, callback) { + if( 'function' === typeof importScripts ) { + importScripts.apply(null, urls); + callback(); + } else { + getScriptsInOrder(urls, callback); + } +} + +function onJSONLoaded () { + data = JSON.parse(this.responseText); + var scriptsToLoad = ['lunr.js']; + if (data.config && data.config.lang && data.config.lang.length) { + lang = data.config.lang; + } + if (lang.length > 1 || lang[0] !== "en") { + scriptsToLoad.push('lunr.stemmer.support.js'); + if (lang.length > 1) { + scriptsToLoad.push('lunr.multi.js'); + } + if (lang.includes("ja") || lang.includes("jp")) { + scriptsToLoad.push('tinyseg.js'); + } + for (var i=0; i < lang.length; i++) { + if (lang[i] != 'en') { + scriptsToLoad.push(['lunr', lang[i], 'js'].join('.')); + } + } + } + loadScripts(scriptsToLoad, onScriptsLoaded); +} + +function onScriptsLoaded () { + console.log('All search scripts loaded, building Lunr index...'); + if (data.config && data.config.separator && data.config.separator.length) { + lunr.tokenizer.separator = new RegExp(data.config.separator); + } + + if (data.index) { + index = lunr.Index.load(data.index); + data.docs.forEach(function (doc) { + documents[doc.location] = doc; + }); + console.log('Lunr pre-built index loaded, search ready'); + } else { + index = lunr(function () { + if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) { + this.use(lunr[lang[0]]); + } else if (lang.length > 1) { + this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility + } + this.field('title'); + this.field('text'); + this.ref('location'); + + for (var i=0; i < data.docs.length; i++) { + var doc = data.docs[i]; + this.add(doc); + documents[doc.location] = doc; + } + }); + console.log('Lunr index built, search ready'); + } + allowSearch = true; + postMessage({config: data.config}); + postMessage({allowSearch: allowSearch}); +} + +function init () { + var oReq = new XMLHttpRequest(); + oReq.addEventListener("load", onJSONLoaded); + var index_path = base_path + '/search_index.json'; + if( 'function' === typeof importScripts ){ + index_path = 'search_index.json'; + } + oReq.open("GET", index_path); + oReq.send(); +} + +function search (query) { + if (!allowSearch) { + console.error('Assets for search still loading'); + return; + } + + var resultDocuments = []; + var results = index.search(query); + for (var i=0; i < results.length; i++){ + var result = results[i]; + doc = documents[result.ref]; + doc.summary = doc.text.substring(0, 200); + resultDocuments.push(doc); + } + return resultDocuments; +} + +if( 'function' === typeof importScripts ) { + onmessage = function (e) { + if (e.data.init) { + init(); + } else if (e.data.query) { + postMessage({ results: search(e.data.query) }); + } else { + console.error("Worker - Unrecognized message: " + e); + } + }; +} diff --git a/security.md b/security.md deleted file mode 100644 index cb59eb8..0000000 --- a/security.md +++ /dev/null @@ -1,5 +0,0 @@ -# Security Policy -Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. - -## Reporting a Vulnerability -Please report any security vulnerabilities in this project utilizing the guidelines [here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). diff --git a/sitemap.xml b/sitemap.xml new file mode 100755 index 0000000..0f8724e --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100755 index 0000000..e43d52e Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/src/Languages/buildFolder.ts b/src/Languages/buildFolder.ts deleted file mode 100644 index e0728a7..0000000 --- a/src/Languages/buildFolder.ts +++ /dev/null @@ -1,192 +0,0 @@ -import path = require("path"); -import * as vscode from 'vscode'; -import * as fs from 'fs'; -import { gConfigAgent, gCscope, gDebugLog, gWorkspacePath } from "../extension"; -import { getRealPath, getRealPathRelative, isWorkspacePath, normalizePath, readLines, split, toPosix } from "../utils"; -import glob = require("fast-glob"); -import { writeEdkCodeFolderFile } from "../edk2CodeFolder"; -import { isFixWorkspacePath } from "../ui/messages"; - -export class BuildFolder { - buildFolderPaths: string[]=[]; - replaceWorkspacePath: string|undefined; - - constructor(folderPath: string[]) { - this.buildFolderPaths = folderPath; - } - - - - async getBuildInfo() { - if (fs.existsSync(path.join(this.buildFolderPaths[0], "BuildOptions"))) { - return await this.getBuildOptions(); - } - } - - /** - * looks for EDK2 `BuildOptions` file and parses it. - * It sets `buildDefines` and `activeDscFiles` - * @param buildOptionsPath Build path were EDK2 compilation was generated - */ - async getBuildOptions() { - try { - gDebugLog.trace("getBuildOptions()"); - // todo: change for multiple build folders - let buildDefines: Map = new Map(); - let dscFiles:Set = new Set(); - - for (const buildOptionsPath of this.buildFolderPaths) { - let lines = readLines(path.join(buildOptionsPath, "BuildOptions")); - for (let l of lines) { - if (l.startsWith("gCommandLineDefines")) { - l = l.replace("gCommandLineDefines: ", "").replace("{", "").replace("}", "").replaceAll("'", ""); - - for (const buildOption of l.split(",")) { - let [val, data] = split(buildOption, ":", 2); - gDebugLog.trace(`Define: ${val}: ${data}`); - buildDefines.set(val.trim(), data.trim()); - } - } - - if (l.startsWith("Active Platform: ")) { - let buildActivePlatform: string = split(l, ":", 2)[1].trim(); - gDebugLog.info(`Active platform: ${buildActivePlatform}`); - if(!fs.existsSync(buildActivePlatform) && !isWorkspacePath(buildActivePlatform)){ - gDebugLog.warning(`Active platform Build "${buildActivePlatform}" is not in current Vscode workspace folder "${gWorkspacePath}"`); - if(await isFixWorkspacePath(buildActivePlatform, gWorkspacePath)){ - const oldWorkspacePath = this.findBuildWorkspacePath(buildActivePlatform); - if (oldWorkspacePath) { - - const newBuildActivePlatform = path.normalize(buildActivePlatform).replace(oldWorkspacePath, gWorkspacePath); - if (fs.existsSync(newBuildActivePlatform)) { - buildActivePlatform = newBuildActivePlatform; - gDebugLog.trace(`Corrected Active platform: ${buildActivePlatform}`); - if(this.replaceWorkspacePath !== undefined && this.replaceWorkspacePath !== oldWorkspacePath){ - gDebugLog.error(`Multiple original workspace paths found: ${this.replaceWorkspacePath} and ${oldWorkspacePath}`); - } - this.replaceWorkspacePath = oldWorkspacePath; - } else { - gDebugLog.error(`Active build platform not found: ${newBuildActivePlatform}`); - } - - } else{ - gDebugLog.warning(`Old workspace path not found for: ${buildActivePlatform}`); - } - } - } - - - buildActivePlatform = getRealPathRelative(buildActivePlatform); - gDebugLog.trace(`Active platform: ${buildActivePlatform}`); - dscFiles.add(buildActivePlatform); - } - } - } - return { buildDefines: buildDefines, dscFiles: Array.from(dscFiles) }; - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showErrorMessage(String(error)); - throw new Error(String(error)); - } - } - - findBuildWorkspacePath(wrongPath:string){ - const wrongPathParts = wrongPath.split(/[\\/]/); - let oldPathWorkspace = []; - while(wrongPathParts.length > 0){ - const testPath = path.join(gWorkspacePath, ...wrongPathParts); - if(fs.existsSync(testPath)){ - return oldPathWorkspace.join(path.sep); - } - const part = wrongPathParts.shift(); - oldPathWorkspace.push(part); - gDebugLog.trace(`Removed part: ${part}`); - } - return undefined; - } - - async copyMapFilesList(){ - let maplist = []; - for (const buildPaths of this.buildFolderPaths) { - let mapPaths = glob.sync(toPosix(path.join(buildPaths,"**","OUTPUT","*.map"))); - for (const m of mapPaths) { - maplist.push(m); - } - } - writeEdkCodeFolderFile("mapFiles.json",JSON.stringify(maplist, null, 2)); - } - - replaceOldWorkspacePath(p:string){ - if(this.replaceWorkspacePath !== undefined){ - return path.normalize(p).replace(this.replaceWorkspacePath, gWorkspacePath); - } - return p; - } - - copyCompileInfoToRoot() { - let cscopeMap = new Map(); - let moduleReport = []; - let compileCommands:string[] = []; - - for (const folder of this.buildFolderPaths) { - - if (!fs.existsSync(path.join(folder, "CompileInfo"))) { - continue; - } - - // Cscope - let cscopeLines = readLines(path.join(folder, "CompileInfo", "cscope.files")); - - for (const l of cscopeLines) { - cscopeMap.set(l.toUpperCase(), this.replaceOldWorkspacePath(l)); - } - - - let compileInfoText = fs.readFileSync(path.join(folder, "CompileInfo", "compile_commands.json")).toString(); - let modulesText = fs.readFileSync(path.join(folder, "CompileInfo", "module_report.json")).toString(); - - if(this.replaceWorkspacePath!==undefined){ - // make path json compatible - const jsonReplacePath = this.replaceWorkspacePath.replaceAll(/\\/g, "\\\\").replaceAll("/", "\\/"); - const jsonWorkspacePath = gWorkspacePath.replaceAll(/\\/g, "\\\\").replaceAll("/", "\\/"); - compileInfoText = compileInfoText.replaceAll(jsonReplacePath, jsonWorkspacePath); - modulesText = modulesText.replaceAll(jsonReplacePath, jsonWorkspacePath); - } - - let commands = JSON.parse(compileInfoText); - // Merge compile commands - for (const cmd of commands) { - compileCommands.push(cmd); - } - - // Merge build report - let modules = JSON.parse(modulesText); - for (const mod of modules) { - moduleReport.push(mod); - } - } - let filteredCscope = []; - for (const value of cscopeMap.values()) { - try { - let cleanValue = value.replace(/\n$/, ""); - filteredCscope.push(cleanValue); - // For .dec files, add the package directory to package paths - let unquoted = cleanValue.replace(/^"|"$/g, ""); - if(unquoted.toLowerCase().endsWith(".dec")){ - let decPackageDir = getRealPathRelative(path.dirname(unquoted)); - gConfigAgent.pushBuildPackagePaths(decPackageDir); - } - } catch (error) { - - } - - } - - gCscope.writeCscopeFile(filteredCscope); - writeEdkCodeFolderFile("module_report.json", JSON.stringify(moduleReport, null, 2)); - writeEdkCodeFolderFile("compile_commands.json", JSON.stringify(compileCommands, null, 2)); - if(compileCommands.length === 0){ - writeEdkCodeFolderFile(".missing", ""); - } - } -} \ No newline at end of file diff --git a/src/Languages/completionProvider.ts b/src/Languages/completionProvider.ts deleted file mode 100644 index f1e29fe..0000000 --- a/src/Languages/completionProvider.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as vscode from 'vscode'; -import { getParserForDocument } from '../edkParser/parserFactory'; -import { gDebugLog } from '../extension'; - - -export class EdkCompletionProvider implements vscode.CompletionItemProvider { - - constructor() { - - } - - async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) { - let parser = await getParserForDocument(document); - if(parser){ - let selectedSymbol = parser.getSelectedSymbol(position); - if (!selectedSymbol) { return []; } - gDebugLog.trace(`Completion for: ${selectedSymbol.toString()}`); - - if (selectedSymbol.onCompletion !== undefined) { - let temp = await selectedSymbol.onCompletion(document, position, token, context); - return temp; - } - } - } -} \ No newline at end of file diff --git a/src/Languages/declarationProvider.ts b/src/Languages/declarationProvider.ts deleted file mode 100644 index 21b1cf3..0000000 --- a/src/Languages/declarationProvider.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as vscode from 'vscode'; -import { getParserForDocument } from '../edkParser/parserFactory'; -import { gDebugLog } from '../extension'; - - -export class EdkDeclarationProvider implements vscode.DeclarationProvider { - - constructor() { - - } - async provideDeclaration(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) { - - let parser = await getParserForDocument(document); - if(parser){ - let selectedSymbol = parser.getSelectedSymbol(position); - if (!selectedSymbol) { return []; } - gDebugLog.trace(`Definition for: ${selectedSymbol.toString()}`); - if (selectedSymbol.onDeclaration !== undefined) { - let temp = await selectedSymbol.onDeclaration(); - return temp; - } - } - - } -} \ No newline at end of file diff --git a/src/Languages/definitionProvider.ts b/src/Languages/definitionProvider.ts deleted file mode 100644 index 0cccf50..0000000 --- a/src/Languages/definitionProvider.ts +++ /dev/null @@ -1,80 +0,0 @@ -import * as vscode from 'vscode'; -import { getParserForDocument } from '../edkParser/parserFactory'; -import { gDebugLog, gEdkWorkspaces } from '../extension'; -import { REGEX_PCD, REGEX_VAR_USAGE } from '../edkParser/commonParser'; -import { split } from '../utils'; - -export class EdkDefinitionProvider implements vscode.DefinitionProvider { - - constructor() { - - } - async provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) { - - // Check if its a variable definition - let word = document.getWordRangeAtPosition(position,REGEX_VAR_USAGE); - if(word){ - let text = document.getText(word); - let wps = await gEdkWorkspaces.getWorkspace(document.uri); - if(wps.length){ - for (const wp of wps) { - let key = document.getText(document.getWordRangeAtPosition(position)); - let definitionLocation = wp.getDefinitionLocation(key); - - if(document.languageId === "edk2_fdf"){ - definitionLocation = wp.definesFdf.getDefinitionLocation(key); - } - - if(definitionLocation){ - return definitionLocation; - }else{ - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showInformationMessage(`${key} is defined in build arguments`); - return; - } - } - } - } - - // Check if word its a PCD - word = document.getWordRangeAtPosition(position,REGEX_PCD); - if(word){ - let text = document.getText(word); - let wps = await gEdkWorkspaces.getWorkspace(document.uri); - if(wps.length){ - for (const wp of wps) { - let [namespace, key] = split(text,".",2); - let pcdsList = wp.getPcds(namespace); - if(pcdsList === undefined){continue;} - let resultPcd = pcdsList.get(key); - if(resultPcd){ - return resultPcd.position; - } - } - } - } - - - - - let parser = await getParserForDocument(document); - if(parser){ - let selectedSymbol = parser.getSelectedSymbol(position); - if (!selectedSymbol) { return []; } - gDebugLog.trace(`Definition for: ${selectedSymbol.toString()}`); - if (selectedSymbol.onDefinition !== undefined) { - let locations: vscode.Location[] = await selectedSymbol.onDefinition(parser); - if (!locations || locations.length === 0) { return []; } - // Return LocationLink[] so VS Code highlights the full symbol range on Ctrl+hover - return locations.map(loc => ({ - originSelectionRange: selectedSymbol!.selectionRange, - targetUri: loc.uri, - targetRange: loc.range, - targetSelectionRange: loc.range, - } as vscode.LocationLink)); - } - } - } - - -} \ No newline at end of file diff --git a/src/Languages/guidProvider.ts b/src/Languages/guidProvider.ts deleted file mode 100644 index 00e4bcb..0000000 --- a/src/Languages/guidProvider.ts +++ /dev/null @@ -1,85 +0,0 @@ - -import * as vscode from 'vscode'; -import { readLines, split, toPosix } from '../utils'; -import { DictHoverProvider } from './symbolProvider'; -import * as fs from 'fs'; -import { gWorkspacePath } from '../extension'; -import path = require('path'); -import { glob } from 'fast-glob'; -import { writeEdkCodeFolderFile, getEdkCodeFolderFilePath } from '../edk2CodeFolder'; - -export class GuidProvider{ - guidProvider: vscode.Disposable|undefined = undefined; - - constructor (){ - - } - - - private async createGuidXrefFile(){ - return await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: "Creating Guid xref file", - cancellable: true - }, async (progress, reject) => { - - return new Promise(async (resolve, token) => { - let guidXref:string[] = []; - - // First check for xref files on all workspace - let lookPath = toPosix(path.join(gWorkspacePath, "**/Guid.xref")); - let fileList = glob.sync(lookPath); - for (const file of fileList) { - let lines = readLines(file); - for (const line of lines) { - // Avoid empty lines - if(line.trim().length > 0){ - guidXref.push(line.replace(" ",",")); - } - } - } - - // Parse fdf files for FV guids - // let fvNameGuidData = await gEdkDatabase.findByName("FvNameGuid","edk2_fdf"); - // for (const symbol of fvNameGuidData) { - // let symbolParent = await symbol.getParent(); - // if(symbolParent){ - // let fvName = symbolParent.name; - // guidXref.push(`${symbol.detail.toUpperCase()},${fvName}`); - // } - - // } - - writeEdkCodeFolderFile("Guid.csv",guidXref.join("\n")); - resolve(); - }); - }); - } - - public async registerProvider(){ - await this.createGuidXrefFile(); - - let guidXrefPath = getEdkCodeFolderFilePath("Guid.csv"); - //Check if guidXref.xref exists - if(fs.existsSync(guidXrefPath)){ - //unregister previous provider - if(this.guidProvider){ - this.guidProvider.dispose(); - } - - - // read guidXref.xref file and create a map - let guidXrefMap = new Map(); - let guidXrefLines = readLines(guidXrefPath); - for (const line of guidXrefLines) { - let data = split(line, ",", 2); - guidXrefMap.set(data[0], data[1]); - } - vscode.languages.registerHoverProvider({ scheme: 'file', language: '*' }, new DictHoverProvider(guidXrefMap, - /[a-fA-F\d]{8}-[a-fA-F\d]{4}-[a-fA-F\d]{4}-[a-fA-F\d]{4}-[a-fA-F\d]{12}/) - ); - } - } - - - } \ No newline at end of file diff --git a/src/Languages/languages.ts b/src/Languages/languages.ts deleted file mode 100644 index 546df8e..0000000 --- a/src/Languages/languages.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Original file from: https://github.com/WalonLi/edk2-vscode - -import * as vscode from 'vscode'; -import { DictHoverProvider, DictHoverProviderDb, EdkSymbolProvider, HelpHoverProvider, JsonCompletionItemLabel, JsonCompletionProvider } from './symbolProvider'; -import { getStaticPath } from '../utils'; -import * as fs from 'fs'; -import { EdkDefinitionProvider } from './definitionProvider'; -import { EdkDeclarationProvider } from './declarationProvider'; -import { EdkCompletionProvider } from './completionProvider'; - - - -export function initLanguages() { - vscode.languages.registerDocumentSymbolProvider({ scheme: 'file', language: 'edk2_dsc' }, new EdkSymbolProvider()); - vscode.languages.registerDefinitionProvider({ scheme: 'file', language: 'edk2_dsc' }, new EdkDefinitionProvider()); - vscode.languages.registerHoverProvider({ scheme: 'file', language: 'edk2_dsc' }, new DictHoverProviderDb()); - - vscode.languages.registerDocumentSymbolProvider({ scheme: 'file', language: 'edk2_inf' }, new EdkSymbolProvider()); - vscode.languages.registerDefinitionProvider({ scheme: 'file', language: 'edk2_inf' }, new EdkDefinitionProvider()); - vscode.languages.registerCompletionItemProvider ({ scheme: 'file', language: 'edk2_inf' }, new EdkCompletionProvider()); - vscode.languages.registerDeclarationProvider ({ scheme: 'file', language: 'edk2_inf' }, new EdkDeclarationProvider()); - - vscode.languages.registerDocumentSymbolProvider({ scheme: 'file', language: 'edk2_dec' }, new EdkSymbolProvider()); - // vscode.languages.registerDefinitionProvider({ scheme: 'file', language: 'edk2_dec' }, new EdkDefinitionProvider()); - - vscode.languages.registerDocumentSymbolProvider({ scheme: 'file', language: 'edk2_fdf' }, new EdkSymbolProvider()); - vscode.languages.registerDefinitionProvider({ scheme: 'file', language: 'edk2_fdf' }, new EdkDefinitionProvider()); - vscode.languages.registerHoverProvider({ scheme: 'file', language: 'edk2_fdf' }, new DictHoverProviderDb()); - - - vscode.languages.registerDocumentSymbolProvider({ scheme: 'file', language: 'edk2_vfr' }, new EdkSymbolProvider()); - vscode.languages.registerDocumentSymbolProvider({ scheme: 'file', language: 'asl' }, new EdkSymbolProvider()); - - // // ASL support - vscode.languages.registerCompletionItemProvider ({ scheme: 'file', language: 'asl' }, new JsonCompletionProvider("acpiHelp.json", - (x:any)=>{return new JsonCompletionItemLabel(x.title.split(" ")[0], x.description);})); - - vscode.languages.registerHoverProvider({ scheme: 'file', language: 'asl' }, new HelpHoverProvider(getStaticPath("acpiHelp.json"), - (x:string, entrie:any)=>{return entrie.title.startsWith(x);}, - [{fieldname:"title", pre:"# ", pos:"\n\n"}, - {fieldname:"syntax", pre:"`", pos:"`\n\n"}, - {fieldname:"arguments", pre:"> ", pos:"\n\n"}, - {fieldname:"description", pre:"", pos:"\n\n *ACPI 6.3*"}]) - ); - - -} - - diff --git a/src/Languages/symbolProvider.ts b/src/Languages/symbolProvider.ts deleted file mode 100644 index 3c839c7..0000000 --- a/src/Languages/symbolProvider.ts +++ /dev/null @@ -1,182 +0,0 @@ -import * as vscode from 'vscode'; -import * as fs from 'fs'; -import { getStaticPath, itsPcdSelected } from '../utils'; -import path = require('path'); -import { CompletionItemKind } from 'vscode'; -import { getParserForDocument } from '../edkParser/parserFactory'; -import { gConfigAgent, gEdkWorkspaces } from '../extension'; -import { Debouncer } from '../debouncer'; -import { DiagnosticManager } from '../diagnostics'; - - -export class EdkSymbolProvider implements vscode.DocumentSymbolProvider { - - constructor() { - vscode.workspace.onDidSaveTextDocument(this.updateEdkWorkspace, this); - - } - - private async updateEdkWorkspace(document: vscode.TextDocument) { - if (document.languageId === 'edk2_dsc' || document.languageId === 'edk2_fdf') { - // create document from dscPath - let wp = await gEdkWorkspaces.getWorkspace(document.uri); - if(wp.length){ - - const debouncer = Debouncer.getInstance(); - debouncer.debounce("updateDocumentSymbols",async () => { - await wp[0].proccessWorkspace(); - }, gConfigAgent.getDelayToRefreshWorkspace()); - - if (document.languageId === 'edk2_fdf') { - await wp[0].fdfPostProcces(document); - } - } - } - - } - - public async provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken) { - - // Create a parser for the document - let parser = await getParserForDocument(document); - if (parser) { - return parser.symbolsTree; - } - return []; - } -} - -export class HelpHoverProvider implements vscode.HoverProvider { - entries: any; - selectionFunction: Function; - fields: { fieldname: string; pre: string; pos: string; }[]; - wordRegex: RegExp | undefined; - constructor(jsonFile: string, selectionFunction: Function, fields: { fieldname: string, pre: string, pos: string }[], wordRegex: RegExp | undefined = undefined) { - if (fs.existsSync(jsonFile)) { - let jsonHelp = jsonFile; - var values = fs.readFileSync(jsonHelp).toString(); - this.entries = JSON.parse(values); - } else { - this.entries = []; - } - this.wordRegex = wordRegex; - this.selectionFunction = selectionFunction; - this.fields = fields; - } - - async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) { - let word = document.getText(document.getWordRangeAtPosition(position, this.wordRegex)); - let selectedHelp = undefined; - if (word !== undefined) { - for (const help of this.entries) { - if (this.selectionFunction(word, help)) { - selectedHelp = help; - } - } - if (selectedHelp !== undefined) { - let hoverData = ""; - for (const field of this.fields) { - if (selectedHelp[field.fieldname] !== "") { - hoverData += field.pre + selectedHelp[field.fieldname] + field.pos; - } - } - return new vscode.Hover(hoverData); - } - } - } -} - - -export class DictHoverProvider implements vscode.HoverProvider { - dictData: Map; - wordRegex: RegExp | undefined; - caseSensitive: boolean = false; - constructor(database: Map, wordRegex: RegExp | undefined = undefined, caseSensitive: boolean = false) { - this.wordRegex = wordRegex; - this.dictData = database; - this.caseSensitive = caseSensitive; - } - - async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) { - - let word = document.getText(document.getWordRangeAtPosition(position, this.wordRegex)); - if (!this.caseSensitive) { - word = word.toUpperCase(); - } - let hoverData = this.dictData.get(word); - if (!hoverData) { return undefined; } - return new vscode.Hover(hoverData); - } -} - - - -export class DictHoverProviderDb implements vscode.HoverProvider { - - constructor() { - - } - - async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) { - let word = document.getText(document.getWordRangeAtPosition(position)); - let line = document.lineAt(position.line).text; - - // Match definition? - if(line.match(new RegExp(`\\$\\(\\s*${word}\\s*\\)`))) { - let wp = await gEdkWorkspaces.getWorkspace(document.uri); - if(wp.length){ - let def = wp[0].getDefinitions().get(word); - if (def) { - return new vscode.Hover(def.value); - }else{ - return new vscode.Hover("Undefined"); - } - } - } - - - let pcd = await itsPcdSelected(document, position); - if (pcd) { - return new vscode.Hover(pcd.value); - } - - - - // return new vscode.Hover(data.value); - } -} - - - - -export class JsonCompletionItemLabel implements vscode.CompletionItemLabel { - label: string; - description: string; - constructor(label: string, description: string) { - this.label = label; - this.description = description; - } -} - -export class JsonCompletionProvider implements vscode.CompletionItemProvider { - entries: any; - completionCreateFunction: Function; - - constructor(jsonFile: string, completionCreateFunction: Function) { - let jsonHelp = getStaticPath(jsonFile); - this.completionCreateFunction = completionCreateFunction; - var values = fs.readFileSync(jsonHelp).toString(); - this.entries = JSON.parse(values); - } - - async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) { - let returnList = []; - for (const help of this.entries) { - let x = this.completionCreateFunction(help); - returnList.push(new vscode.CompletionItem(x, CompletionItemKind.Keyword)); - } - return returnList; - } -} - - diff --git a/src/buildEdk2.ts b/src/buildEdk2.ts deleted file mode 100644 index cc0f5aa..0000000 --- a/src/buildEdk2.ts +++ /dev/null @@ -1,627 +0,0 @@ -import * as vscode from 'vscode'; -import * as path from 'path'; -import * as fs from 'fs'; -import { gConfigAgent, gDebugLog, gWorkspacePath } from './extension'; -import { readEdkCodeFolderFile, writeEdkCodeFolderFile, deleteEdkCodeFolderFile, getEdkCodeFolderFilePath } from './edk2CodeFolder'; - -let buildFormPanel: vscode.WebviewPanel | undefined; - -const BUILD_CONFIG_FILE = 'edk2_build_configuration.json'; -const GLOBAL_CONFIG_KEY = '__global__'; - -export interface BuildInvocation { - /** Absolute or workspace-relative path to the DSC to build. */ - dscPath?: string; - /** Absolute or workspace-relative path to an INF to build with `-m`. */ - modulePath?: string; -} - -/** - * Global build configuration stored in .edkCode/edk2_build_configuration.json. - * Shared across all module builds. Extendable for future global settings. - */ -interface GlobalBuildConfig { - /** EDK2 workspace root containing edksetup.bat/sh. Empty = use VS Code workspace path. */ - edkSetupPath: string; - /** NASM assembler path prefix. Exported as NASM_PREFIX. */ - nasmPrefix: string; - /** IASL compiler path prefix. Exported as IASL_PREFIX. */ - iaslPrefix: string; - /** Path to EDK2 BaseTools binaries. Exported as EDK_TOOLS_BIN. */ - edkToolsBin: string; - /** Optional WORKSPACE directory override. Empty = auto-compute from platform DSC location. */ - workspaceDir: string; -} - -const DEFAULT_GLOBAL_CONFIG: GlobalBuildConfig = { - edkSetupPath: '', - nasmPrefix: '', - iaslPrefix: '', - edkToolsBin: '', - workspaceDir: '' -}; - -interface DefineEntry { - name: string; - value: string; -} - -interface BuildFormState { - platform: string; - module: string; - arch: string; - target: string; - toolchain: string; - action: string; - skuid: string; - threads: string; - fdfFile: string; - romImage: string; - fvImage: string; - capsuleImage: string; - skipAutogen: boolean; - reParse: boolean; - caseInsensitive: boolean; - warningAsError: boolean; - logFile: string; - silent: boolean; - quiet: boolean; - verbose: boolean; - debug: string; - defines: DefineEntry[]; - reportFile: string; - reportType: string[]; - flag: string; - noCache: boolean; - confDir: string; - checkUsage: boolean; - ignoreSources: boolean; - pcds: string[]; - cmdLen: string; - hash: boolean; - binaryDestination: string; - binarySource: string; - genfdsMultiThread: boolean; - noGenfdsMultiThread: boolean; - disableIncludePathCheck: boolean; - extraArgs: string[]; - packagePaths: string[]; - /** DSC choices to populate the dropdown (not persisted). */ - dscPaths: string[]; -} - -/** Key used to store/load per-module config in the JSON file. */ -function configKey(state: { platform: string; module: string }): string { - return state.module || state.platform || '__default__'; -} - -function loadAllConfig(): Record { - const raw = readEdkCodeFolderFile(BUILD_CONFIG_FILE); - if (!raw) { return {}; } - try { return JSON.parse(raw); } catch { return {}; } -} - -function saveAllConfig(all: Record): void { - writeEdkCodeFolderFile(BUILD_CONFIG_FILE, JSON.stringify(all, null, 2)); -} - -function loadGlobalConfig(): GlobalBuildConfig { - const all = loadAllConfig(); - return { ...DEFAULT_GLOBAL_CONFIG, ...(all[GLOBAL_CONFIG_KEY] ?? {}) }; -} - -function saveGlobalConfig(global: GlobalBuildConfig): void { - const all = loadAllConfig(); - all[GLOBAL_CONFIG_KEY] = global; - saveAllConfig(all); -} - -function loadSavedConfig(key: string): Partial | undefined { - const all = loadAllConfig(); - return all[key] ?? undefined; -} - -function saveConfig(key: string, state: BuildFormState): void { - const all = loadAllConfig(); - // Don't persist the dscPaths list — it's runtime only - const { dscPaths, ...toSave } = state; - all[key] = toSave; - saveAllConfig(all); -} - -function deleteSavedConfig(key: string): void { - const all = loadAllConfig(); - delete all[key]; - // Keep at least global config - if (Object.keys(all).length === 0 || (Object.keys(all).length === 1 && all[GLOBAL_CONFIG_KEY])) { - if (Object.keys(all).length === 0) { - deleteEdkCodeFolderFile(BUILD_CONFIG_FILE); - } else { - saveAllConfig(all); - } - } else { - saveAllConfig(all); - } -} - -/** - * Public entry point for the EDK2 build command. - * Always opens the build configuration form (webview) first, then runs - * the build in a terminal when the user clicks "Build". - */ -export async function buildEdk2Workspace(options?: BuildInvocation) { - const isWindows = process.platform === 'win32'; - - // Load global config (edkSetupPath, nasmPrefix, etc.) - const globalConfig = loadGlobalConfig(); - - // Get DSC paths - const dscPaths = gConfigAgent.getBuildDscPaths(); - if (!dscPaths || dscPaths.length === 0) { - void vscode.window.showErrorMessage('No DSC paths configured. Please configure DSC paths first.'); - return; - } - - // Determine pre-selected DSC - let selectedDsc: string | undefined = options?.dscPath; - if (selectedDsc) { - // Normalize: if dscPath is absolute, find the matching relative entry in dscPaths - const match = dscPaths.find(d => - d === selectedDsc || - path.resolve(gWorkspacePath, d) === path.resolve(selectedDsc!) || - path.normalize(d) === path.normalize(selectedDsc!) - ); - if (match) { - selectedDsc = match; - } - } - if (!selectedDsc) { - if (dscPaths.length === 1) { - selectedDsc = dscPaths[0]; - } else { - const picked = await vscode.window.showQuickPick(dscPaths, { - placeHolder: 'Select DSC file to build', - title: 'EDK2 Build' - }); - if (!picked) { return; } - selectedDsc = picked; - } - } - - // Build defaults from settings - const defaultState: BuildFormState = { - platform: selectedDsc, - module: options?.modulePath ?? '', - arch: gConfigAgent.getBuildArch(), - target: gConfigAgent.getBuildTarget(), - toolchain: gConfigAgent.getBuildToolchain(), - action: '', - skuid: '', - threads: '', - fdfFile: '', - romImage: '', - fvImage: '', - capsuleImage: '', - skipAutogen: false, - reParse: false, - caseInsensitive: false, - warningAsError: false, - logFile: '', - silent: false, - quiet: false, - verbose: false, - debug: '', - defines: Array.from(gConfigAgent.getBuildDefines().entries()).map(([k, v]) => ({ name: k, value: v })), - reportFile: '', - reportType: [], - flag: '', - noCache: false, - confDir: '', - checkUsage: false, - ignoreSources: false, - pcds: [], - cmdLen: '', - hash: false, - binaryDestination: '', - binarySource: '', - genfdsMultiThread: false, - noGenfdsMultiThread: false, - disableIncludePathCheck: false, - extraArgs: gConfigAgent.getBuildExtraArgs().filter(a => a.trim()), - packagePaths: gConfigAgent.getBuildPackagePaths().filter(p => p.trim()), - dscPaths: dscPaths - }; - - // Load saved config if available - const key = configKey(defaultState); - const saved = loadSavedConfig(key); - const initial: BuildFormState = saved - ? { ...defaultState, ...saved, dscPaths } - : defaultState; - - // Open the form (stays open; handles build internally) - showBuildForm(initial, defaultState, globalConfig, isWindows); -} - -/** Validation error with associated field ID for highlighting in the form. */ -interface ValidationError { - field: string; - message: string; -} - -/** Resolve a config path: if relative, resolve against workspace root; if absolute, use as-is. */ -function resolveConfigPath(p: string): string { - if (!p) { return ''; } - if (path.isAbsolute(p)) { return p; } - return path.join(gWorkspacePath, p); -} - -/** Validate global config paths. Returns an array of validation errors (empty if all OK). */ -function validateGlobalConfig(config: GlobalBuildConfig): ValidationError[] { - const errors: ValidationError[] = []; - - // EDK Setup Path: must point to edksetup.bat or edksetup.sh - const rawSetup = config.edkSetupPath.trim(); - if (rawSetup) { - const setupPath = resolveConfigPath(rawSetup); - if (!fs.existsSync(setupPath)) { - errors.push({ field: 'edkSetupPath', message: `EDK2 setup script not found: ${setupPath}` }); - } else if (fs.statSync(setupPath).isDirectory()) { - errors.push({ field: 'edkSetupPath', message: `Expected a file (edksetup.bat/.sh), got a directory: ${setupPath}` }); - } - } else { - // Default: look for edksetup in workspace root - const isWindows = process.platform === 'win32'; - const defaultScript = path.join(gWorkspacePath, isWindows ? 'edksetup.bat' : 'edksetup.sh'); - if (!fs.existsSync(defaultScript)) { - errors.push({ field: 'edkSetupPath', message: `EDK2 setup script not found in workspace: ${defaultScript}` }); - } - } - - // NASM Prefix: must point to nasm executable - const rawNasm = config.nasmPrefix.trim(); - if (rawNasm) { - const nasmPath = resolveConfigPath(rawNasm); - if (!fs.existsSync(nasmPath)) { - errors.push({ field: 'nasmPrefix', message: `NASM executable not found: ${nasmPath}` }); - } else if (fs.statSync(nasmPath).isDirectory()) { - errors.push({ field: 'nasmPrefix', message: `Expected a file (nasm executable), got a directory: ${nasmPath}` }); - } - } - - // IASL Prefix: must point to iasl executable - const rawIasl = config.iaslPrefix.trim(); - if (rawIasl) { - const iaslPath = resolveConfigPath(rawIasl); - if (!fs.existsSync(iaslPath)) { - errors.push({ field: 'iaslPrefix', message: `IASL executable not found: ${iaslPath}` }); - } else if (fs.statSync(iaslPath).isDirectory()) { - errors.push({ field: 'iaslPrefix', message: `Expected a file (iasl executable), got a directory: ${iaslPath}` }); - } - } - - // EDK Tools Bin: must be an existing directory - const rawToolsBin = config.edkToolsBin.trim(); - if (rawToolsBin) { - const toolsBinPath = resolveConfigPath(rawToolsBin); - if (!fs.existsSync(toolsBinPath)) { - errors.push({ field: 'edkToolsBin', message: `EDK_TOOLS_BIN directory not found: ${toolsBinPath}` }); - } else if (!fs.statSync(toolsBinPath).isDirectory()) { - errors.push({ field: 'edkToolsBin', message: `Expected a directory, got a file: ${toolsBinPath}` }); - } - } - - return errors; -} - -/** Internal: assemble the command line from form state and execute it in a terminal. */ -async function runBuild(state: BuildFormState, edkRoot: string, isWindows: boolean, globalConfig: GlobalBuildConfig) { - // Derive NASM_PREFIX: directory of the nasm executable, ending with separator - const rawNasm = (globalConfig.nasmPrefix || '').trim(); - const nasmPrefix = rawNasm ? path.dirname(resolveConfigPath(rawNasm)) + path.sep : ''; - - // Derive IASL_PREFIX: directory of the iasl executable, ending with separator - const rawIasl = (globalConfig.iaslPrefix || '').trim(); - const iaslPrefix = rawIasl ? path.dirname(resolveConfigPath(rawIasl)) + path.sep : ''; - - // EDK_TOOLS_BIN: resolve as-is (already validated as a directory) - const edkToolsBin = (globalConfig.edkToolsBin || '').trim() - ? resolveConfigPath(globalConfig.edkToolsBin.trim()) : ''; - - // Derive setup script name and edkRoot directory from edkSetupPath - const rawSetup = (globalConfig.edkSetupPath || '').trim(); - let setupScript: string; - if (rawSetup) { - const resolvedSetup = resolveConfigPath(rawSetup); - edkRoot = path.dirname(resolvedSetup); - setupScript = path.basename(resolvedSetup); - } else { - setupScript = isWindows ? 'edksetup.bat' : 'edksetup.sh'; - } - - // Package paths - const packagePaths = (state.packagePaths || []).map(s => s.trim()).filter(s => s.length > 0); - - /** - * Convert an absolute INF/DSC path into a path that EDK2 `build` can resolve. - */ - const toEdkRelative = (p: string): string => { - if (!p) { return p; } - if (!path.isAbsolute(p)) { return p; } - const roots = [edkRoot, ...packagePaths]; - for (const root of roots) { - if (!root) { continue; } - const rel = path.relative(root, p); - if (rel && !rel.startsWith('..') && !path.isAbsolute(rel)) { - return rel; - } - } - return p; - }; - - const platformArg = toEdkRelative(state.platform); - const moduleArg = toEdkRelative(state.module); - - // Compute the effective workspace root (WORKSPACE env variable / CWD for edksetup). - // If the user explicitly set workspaceDir in global config, use that. - // Otherwise, auto-compute from platform DSC location. - let workspaceRoot = edkRoot; - if (globalConfig.workspaceDir) { - workspaceRoot = path.isAbsolute(globalConfig.workspaceDir) - ? globalConfig.workspaceDir - : path.resolve(gWorkspacePath, globalConfig.workspaceDir); - } else if (platformArg && !path.isAbsolute(platformArg)) { - const candidates = new Set(); - candidates.add(edkRoot); - for (const p of packagePaths) { - if (path.isAbsolute(p)) { - candidates.add(p); - candidates.add(path.dirname(p)); - } - } - for (const candidate of candidates) { - if (fs.existsSync(path.join(candidate, platformArg))) { - workspaceRoot = candidate; - break; - } - } - } - - // If workspaceRoot differs from edkRoot, use full path for the setup script - const setupScriptCall = (workspaceRoot !== edkRoot) - ? path.join(edkRoot, setupScript) - : setupScript; - - // Compose build args — use absolute paths for -p and -m - // Note: platformArg/moduleArg are relative to gWorkspacePath (VS Code workspace root), - // not to workspaceRoot (EDK2 WORKSPACE), so resolve against gWorkspacePath. - const args: string[] = []; - if (platformArg) { - const absPlat = path.isAbsolute(platformArg) ? platformArg : path.resolve(gWorkspacePath, platformArg); - args.push(`-p ${absPlat}`); - } - if (moduleArg) { - const absMod = path.isAbsolute(moduleArg) ? moduleArg : path.resolve(gWorkspacePath, moduleArg); - args.push(`-m ${absMod}`); - } - if (state.arch) { - // Support multiple architectures separated by space or comma (e.g. "IA32 X64") - const archs = state.arch.split(/[\s,]+/).filter(Boolean); - for (const a of archs) { args.push(`-a ${a}`); } - } - if (state.target) { args.push(`-b ${state.target}`); } - if (state.toolchain) { args.push(`-t ${state.toolchain}`); } - if (state.skuid) { args.push(`-x ${state.skuid}`); } - if (state.threads) { args.push(`-n ${state.threads}`); } - if (state.fdfFile) { args.push(`-f ${state.fdfFile}`); } - if (state.romImage) { args.push(`-r ${state.romImage}`); } - if (state.fvImage) { args.push(`-i ${state.fvImage}`); } - if (state.capsuleImage) { args.push(`-C ${state.capsuleImage}`); } - if (state.skipAutogen) { args.push(`-u`); } - if (state.reParse) { args.push(`-e`); } - if (state.caseInsensitive) { args.push(`-c`); } - if (state.warningAsError) { args.push(`-w`); } - if (state.logFile) { args.push(`-j ${state.logFile}`); } - if (state.silent) { args.push(`-s`); } - if (state.quiet) { args.push(`-q`); } - if (state.verbose) { args.push(`-v`); } - if (state.debug) { args.push(`-d ${state.debug}`); } - - // Defines: array of {name, value} - for (const def of (state.defines || [])) { - if (def.name) { - const val = def.value.includes(' ') ? `"${def.value}"` : def.value; - args.push(`-D ${def.name}=${val}`); - } - } - - if (state.reportFile) { args.push(`-y ${state.reportFile}`); } - for (const rt of state.reportType || []) { - if (rt) { args.push(`-Y ${rt}`); } - } - if (state.flag) { args.push(`-F ${state.flag}`); } - if (state.noCache) { args.push(`-N`); } - if (state.confDir) { args.push(`--conf=${state.confDir}`); } - if (state.checkUsage) { args.push(`--check-usage`); } - if (state.ignoreSources) { args.push(`--ignore-sources`); } - - // PCDs: array of strings - for (const pcd of (state.pcds || [])) { - const trimmed = pcd.trim(); - if (trimmed) { args.push(`--pcd=${trimmed}`); } - } - - if (state.cmdLen) { args.push(`-l ${state.cmdLen}`); } - if (state.hash) { args.push(`--hash`); } - if (state.binaryDestination) { args.push(`--binary-destination=${state.binaryDestination}`); } - if (state.binarySource) { args.push(`--binary-source=${state.binarySource}`); } - if (state.genfdsMultiThread) { args.push(`--genfds-multi-thread`); } - if (state.noGenfdsMultiThread) { args.push(`--no-genfds-multi-thread`); } - if (state.disableIncludePathCheck) { args.push(`--disable-include-path-check`); } - - // Extra args: array of strings - for (const a of (state.extraArgs || [])) { - const trimmed = a.trim(); - if (trimmed) { args.push(trimmed); } - } - - // Trailing positional action keyword - if (state.action) { args.push(state.action); } - - const buildArgsStr = args.join(' '); - - let cmd: string; - if (isWindows) { - // On Windows, `set "VAR=value"` already preserves spaces — no inner quoting needed - const pkgPath = packagePaths.join(';'); - const parts: string[] = []; - parts.push(`set "WORKSPACE=${workspaceRoot}"`); - parts.push(`set "PACKAGES_PATH=${pkgPath}"`); - if (nasmPrefix) { parts.push(`set "NASM_PREFIX=${nasmPrefix}"`); } - if (iaslPrefix) { parts.push(`set "IASL_PREFIX=${iaslPrefix}"`); } - if (edkToolsBin) { parts.push(`set "EDK_TOOLS_BIN=${edkToolsBin}"`); } - parts.push(`call ${setupScriptCall}`); - parts.push(`build ${buildArgsStr}`); - cmd = parts.join(' && '); - } else { - // On Linux, the outer double-quotes in export protect spaces - const pkgPath = packagePaths.join(':'); - const parts: string[] = []; - parts.push(`export WORKSPACE="${workspaceRoot}"`); - parts.push(`export PACKAGES_PATH="${pkgPath}"`); - if (nasmPrefix) { parts.push(`export NASM_PREFIX="${nasmPrefix}"`); } - if (iaslPrefix) { parts.push(`export IASL_PREFIX="${iaslPrefix}"`); } - if (edkToolsBin) { parts.push(`export EDK_TOOLS_BIN="${edkToolsBin}"`); } - parts.push(`. ${setupScriptCall}`); - parts.push(`build ${buildArgsStr}`); - cmd = parts.join(' && '); - } - - gDebugLog.info(`EDK2 Build command: ${cmd}`); - - // Use a VS Code Task so we get proper process lifecycle tracking - const shellExec = isWindows - ? new vscode.ShellExecution(cmd, { cwd: workspaceRoot }) - : new vscode.ShellExecution(cmd, { cwd: workspaceRoot }); - - const taskDef: vscode.TaskDefinition = { type: 'edk2build' }; - const task = new vscode.Task( - taskDef, - vscode.TaskScope.Workspace, - 'EDK2 Build', - 'edk2code', - shellExec - ); - task.presentationOptions = { - reveal: vscode.TaskRevealKind.Always, - panel: vscode.TaskPanelKind.Shared, - clear: true - }; - - const execution = await vscode.tasks.executeTask(task); - - // Wait for the task process to end - return new Promise((resolve) => { - const disposable = vscode.tasks.onDidEndTaskProcess((e) => { - if (e.execution === execution) { - disposable.dispose(); - resolve(); - } - }); - }); -} - -// ──────────────────────────────────────────────────────────────────────────── -// Build configuration form (webview) -// ──────────────────────────────────────────────────────────────────────────── - -function getFormHtml(extensionPath: string): string { - const htmlPath = path.join(extensionPath, 'static', 'buildForm.html'); - return fs.readFileSync(htmlPath, 'utf8'); -} - -function showBuildForm(initial: BuildFormState, defaults: BuildFormState, globalConfig: GlobalBuildConfig, isWindows: boolean): void { - if (buildFormPanel) { - // If already open, just reveal and re-init - buildFormPanel.reveal(); - buildFormPanel.webview.postMessage({ command: 'init', state: initial, globalConfig, workspacePath: gWorkspacePath }); - return; - } - - // Get extension path for loading HTML - const ext = vscode.extensions.getExtension('intel-corporation.edk2code'); - const extensionPath = ext?.extensionPath ?? path.join(__dirname, '..'); - - const panel = vscode.window.createWebviewPanel( - 'edk2code.buildForm', - 'EDK2 Build Configuration', - vscode.ViewColumn.Active, - { enableScripts: true, retainContextWhenHidden: true, enableFindWidget: true } - ); - buildFormPanel = panel; - - panel.onDidDispose(() => { - buildFormPanel = undefined; - }); - - panel.webview.onDidReceiveMessage(async (msg: any) => { - if (!msg) { return; } - if (msg.command === 'ready') { - // Send initial state + global config to webview - panel.webview.postMessage({ command: 'init', state: initial, globalConfig, workspacePath: gWorkspacePath }); - } else if (msg.command === 'build') { - const state = msg.state as BuildFormState; - const formGlobal = msg.globalConfig as GlobalBuildConfig; - - // Save global config - if (formGlobal) { - saveGlobalConfig(formGlobal); - } - - // Persist the submitted state - saveConfig(configKey(state), state); - - // Re-read global config - const updatedGlobal = loadGlobalConfig(); - - // Validate - const errors = validateGlobalConfig(updatedGlobal); - if (errors.length > 0) { - // Send validation errors to webview for highlighting - panel.webview.postMessage({ command: 'validationErrors', errors }); - return; - } - - // Disable form during build - panel.webview.postMessage({ command: 'buildStarted' }); - - // Derive edkRoot from setup script path (runBuild will also do this, but we need it for cwd) - const rawSetup = updatedGlobal.edkSetupPath.trim(); - let finalEdkRoot: string; - if (rawSetup) { - finalEdkRoot = path.dirname(resolveConfigPath(rawSetup)); - } else { - finalEdkRoot = process.env['WORKSPACE'] || gWorkspacePath; - } - - await runBuild(state, finalEdkRoot, isWindows, updatedGlobal); - - // Re-enable form after build command is sent - panel.webview.postMessage({ command: 'buildFinished' }); - } else if (msg.command === 'cancel') { - panel.dispose(); - } else if (msg.command === 'openConfig') { - const filePath = getEdkCodeFolderFilePath(BUILD_CONFIG_FILE); - const uri = vscode.Uri.file(filePath); - vscode.commands.executeCommand('vscode.open', uri); - } else if (msg.command === 'reset') { - // Delete saved config and re-initialize with defaults - deleteSavedConfig(configKey(initial)); - panel.webview.postMessage({ command: 'init', state: defaults, globalConfig: DEFAULT_GLOBAL_CONFIG }); - } - }); - - panel.webview.html = getFormHtml(extensionPath); -} - - diff --git a/src/callHiearchy.ts b/src/callHiearchy.ts deleted file mode 100644 index f2f1de9..0000000 --- a/src/callHiearchy.ts +++ /dev/null @@ -1,81 +0,0 @@ -import * as vscode from 'vscode'; -import { CallHierarchyItem, SemanticTokens, SymbolKind } from 'vscode'; -import { gCscope } from './extension'; -export class Edk2CallHierarchyProvider implements vscode.CallHierarchyProvider { - - constructor(){ - vscode.languages.registerCallHierarchyProvider( - { - scheme: 'file', - language: 'c' - }, - this - ); - } - - prepareCallHierarchy(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult { - const range = document.getWordRangeAtPosition(position); - if(!range){return[];} - const word = document.getText(range); - return new CallHierarchyItem(SymbolKind.Method, word, "", document.uri, range, range); - } - - async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken) { - - let allLocations:any[] = await gCscope.getCaller(item.name); - - // Filter results to only show files used in compilation - let filteredLocations:vscode.CallHierarchyIncomingCall[] = []; - for (const result of allLocations) { - let fileUri = vscode.Uri.file(result.file); - if(!gCscope.includesFile(fileUri)){continue;} - let namePosition = result.snipped.indexOf(item.name); - let pos = new vscode.Position(result.line, namePosition); - let currentRange = new vscode.Range(pos, pos); - let caller = new CallHierarchyItem( - SymbolKind.Function, - result.name, - `${result.file}: ${result.line + 1}`, - fileUri, - currentRange, - currentRange - ); - filteredLocations.push( - new vscode.CallHierarchyIncomingCall( - caller, - [currentRange] - ) - ); - } - return filteredLocations; - } - - async provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken){ - let allLocations:any[] = await gCscope.getCallee(item.name); - - // Filter results to only show files used in compilation - let filteredLocations:vscode.CallHierarchyOutgoingCall[] = []; - for (const result of allLocations) { - let namePosition = result.snipped.indexOf(result.name); - let pos = new vscode.Position(result.line, namePosition); - let currentRange = new vscode.Range(pos, pos); - let caller = new CallHierarchyItem( - SymbolKind.Function, - result.name, - `${result.file}: ${result.line}`, - vscode.Uri.file(result.file), - currentRange, - currentRange - ); - filteredLocations.push( - new vscode.CallHierarchyOutgoingCall( - caller, - [currentRange] - ) - ); - } - return filteredLocations; - } - - - } \ No newline at end of file diff --git a/src/compileCommands.ts b/src/compileCommands.ts deleted file mode 100644 index ee0cb9e..0000000 --- a/src/compileCommands.ts +++ /dev/null @@ -1,108 +0,0 @@ - - -import path = require("path"); -import * as fs from 'fs'; -import { readEdkCodeFolderFile, writeEdkCodeFolderFile } from "./edk2CodeFolder"; -import { normalizePath } from "./utils"; - -interface CompileCommandsEntryJson{ - command: string; - directory: string; - file: string; -} - -export class CompileCommandsEntry{ - command: string; - directory: string; - file: string; - - constructor(command: string, directory: string, file: string){ - this.command = command; - this.directory = directory; - this.file = normalizePath(file); - } - - backup(){ - const compileCommandsText = readEdkCodeFolderFile("compile_commands.json"); - if(compileCommandsText){ - writeEdkCodeFolderFile("backup_compile_commands.json", compileCommandsText); - } - } - - restore(){ - const compileCommandsText = readEdkCodeFolderFile("backup_compile_commands.json"); - if(compileCommandsText){ - writeEdkCodeFolderFile("compile_commands.json", compileCommandsText); - } - } - - - - getDefines(): string[]{ - const defines: string[] = []; - // Match -D or /D flags preceded by whitespace (to avoid matching inside paths) - const match = this.command.match(/(?<=\s)-D\s*[^ ]+|(?<=\s)\/D\s*[^ ]+/g); - if (match) { - match.forEach((define) => { - // Remove leading -D or /D and trim whitespace - defines.push(define.replace(/^-D\s*|\/D\s*/g, '').trim()); - }); - } - return defines; - } - - getIncludePaths(): string[] { - const includePaths: string[] = []; - // Combine patterns for gcc (-I) and msbuild (/I) - const match = this.command.match(/(-I\s*[^ ]+)|(\/I\s*[^ ]+)/g); - if (match) { - match.forEach((includePath) => { - // Remove leading -I or /I and trim whitespace - includePaths.push(includePath.replace(/^-I\s*|\/I\s*/g, '').trim()); - }); - } - return includePaths; - } - -} - -export class CompileCommands{ - compileCommands: Map = new Map(); - - - - load(){ - const compileCommandsText = readEdkCodeFolderFile("compile_commands.json"); - if(compileCommandsText){ - const compileCommandsObject = JSON.parse(compileCommandsText); - // Populate compileCommands Map based on the file name - compileCommandsObject.forEach((entry: CompileCommandsEntryJson) => { - // Normalize the file path - const filePath = normalizePath(entry.file); - this.compileCommands.set(filePath, new CompileCommandsEntry(entry.command, entry.directory, entry.file)); - }); - } - } - - getCompileCommandForFile(file: string): CompileCommandsEntry|undefined{ - const filePath = normalizePath(file); - return this.compileCommands.get(filePath); - } - - addCompileCommandForFile(entry:CompileCommandsEntry){ - this.compileCommands.set(entry.file, entry); - this.save(); - } - - save(){ - const compileCommandsObject: CompileCommandsEntryJson[] = []; - this.compileCommands.forEach((entry, file) => { - compileCommandsObject.push({ - command: entry.command, - directory: entry.directory, - file: file - }); - }); - writeEdkCodeFolderFile("compile_commands.json", JSON.stringify(compileCommandsObject, null, 4)); - } -} \ No newline at end of file diff --git a/src/compileFile.ts b/src/compileFile.ts deleted file mode 100644 index 2c3e5d1..0000000 --- a/src/compileFile.ts +++ /dev/null @@ -1,97 +0,0 @@ -import * as vscode from 'vscode'; -import * as path from 'path'; -import * as fs from 'fs'; -import * as os from 'os'; -import { gCompileCommands } from './extension'; -import { CompileCommandsEntry } from './compileCommands'; - -function getCompilerName(command: string): string { - const match = command.match(/^"?([^"\s]+)"?/); - return match ? path.basename(match[1]) : 'unknown'; -} - -function getOutputFile(command: string): string { - const match = command.match(/-o\s+(\S+)/); - return match ? match[1] : 'N/A'; -} - -function getFlags(command: string): string[] { - const flags: string[] = []; - // Match flags that are not -D, -I, -o, or the compiler/source file - const match = command.match(/\s(-[^DIo]\S*)/g); - if (match) { - match.forEach(f => flags.push(f.trim())); - } - return flags; -} - -function buildReport(entry: CompileCommandsEntry): string { - const fileName = path.basename(entry.file); - const compiler = getCompilerName(entry.command); - const output = getOutputFile(entry.command); - const defines = entry.getDefines(); - const includes = entry.getIncludePaths(); - - const lines: string[] = []; - lines.push('---------------------------------------------------------------'); - lines.push(`| EDK2 Compile: ${fileName}`); - lines.push('---------------------------------------------------------------'); - lines.push(`| Compiler: ${compiler}`); - lines.push(`| Source: ${entry.file}`); - lines.push(`| Output: ${output}`); - lines.push(`| Directory: ${entry.directory}`); - lines.push('---------------------------------------------------------------'); - lines.push(`| Defines (${defines.length}):`); - defines.forEach(d => lines.push(`| -D ${d}`)); - lines.push('---------------------------------------------------------------'); - lines.push(`| Include Paths (${includes.length}):`); - includes.forEach(i => lines.push(`| ${i}`)); - lines.push('---------------------------------------------------------------'); - return lines.join('\n'); -} - -export async function compileCFile(fileUri?: vscode.Uri) { - let filePath: string; - if (fileUri) { - filePath = fileUri.fsPath; - } else { - const editor = vscode.window.activeTextEditor; - if (!editor) { - void vscode.window.showErrorMessage('No active editor found.'); - return; - } - filePath = editor.document.uri.fsPath; - } - - gCompileCommands.load(); - const entry = gCompileCommands.getCompileCommandForFile(filePath); - if (!entry) { - void vscode.window.showErrorMessage(`No compile command found for ${path.basename(filePath)}`); - return; - } - - const report = buildReport(entry); - - // Write report to a separate text file to avoid shell escaping issues - const isWindows = os.platform() === 'win32'; - const reportPath = path.join(os.tmpdir(), 'edk2_compile_report.txt'); - fs.writeFileSync(reportPath, report); - - // Write command to a temp script to avoid terminal line-length limits - const scriptExt = isWindows ? '.bat' : '.sh'; - const scriptPath = path.join(os.tmpdir(), `edk2_compile${scriptExt}`); - const fileName = path.basename(filePath); - - let scriptContent: string; - if (isWindows) { - scriptContent = `@echo off\ntype "${reportPath}"\necho.\ncd /d "${entry.directory}"\n${entry.command}\nif %ERRORLEVEL% EQU 0 (echo Compilation successful: ${fileName}) else (echo Compilation FAILED: ${fileName})`; - } else { - scriptContent = `#!/bin/bash\ncat "${reportPath}"\necho ""\ncd "${entry.directory}"\n${entry.command}\nif [ $? -eq 0 ]; then echo "Compilation successful: ${fileName}"; else echo "Compilation FAILED: ${fileName}"; fi`; - } - fs.writeFileSync(scriptPath, scriptContent, { mode: 0o755 }); - - const terminal = vscode.window.createTerminal({ name: `Compile: ${fileName}`, cwd: entry.directory }); - terminal.show(); - const runCmd = isWindows ? `"${scriptPath}"` : `bash "${scriptPath}"`; - terminal.sendText(runCmd); -} diff --git a/src/configuration.ts b/src/configuration.ts deleted file mode 100644 index 365436c..0000000 --- a/src/configuration.ts +++ /dev/null @@ -1,430 +0,0 @@ -import path = require('path'); -import * as vscode from 'vscode'; -import { gDebugLog, gWorkspacePath } from './extension'; -import * as fs from 'fs'; -import { LogLevel } from './debugLog'; -import { askReloadFiles } from './ui/messages'; -import { readFile } from './utils'; -import { SettingsPanel } from './settings/settingsPanel'; -import { getEdkCodeFolderFilePath, existsEdkCodeFolderFile, writeEdkCodeFolderFile } from './edk2CodeFolder'; -import { TernarySearchTree } from './ternarySearchTree'; - - -export interface WorkspaceConfig { - packagePaths:string[]; - dscPaths:string[]; - buildDefines:string[]; - workspaceTreeFilters?: number[]; -} - -export interface WorkspaceConfigErrors{ - packagePaths:string; - dscPaths:string; - buildDefines:string; -} - -export class ConfigAgent { - - getWorkspaceErrors(): WorkspaceConfigErrors | null { - return {packagePaths:"", dscPaths:"", buildDefines:""}; - } - - - - public vscodeSettings: vscode.WorkspaceConfiguration; - - private reloadConfigs = ["dscPaths", "buildDefines"]; - private configFileWatcher: vscode.FileSystemWatcher | null = null; - private propertiesFile: vscode.Uri | undefined | null = undefined; // undefined and null values are handled differently - private settingsPanel:SettingsPanel|undefined; - - private workspaceConfig:WorkspaceConfig; - private settingsFileName: string = "edk2_workspace_properties.json"; - - /** - * Temporary T-tree file index built when the workspace is being processed. - * Used by PathFind as a fast lookup while packagePaths are not yet populated. - * Set to `null` when the processing is finished. - */ - private _fileIndex: TernarySearchTree | null = null; - - /** - * Tracks whether the last workspace processing completed successfully. - * When `false`, the next `loadConfig` / `proccessWorkspace` will build - * a temporary T-tree so PathFind can resolve files without relying on - * the (still-empty) packagePaths. - */ - private _workspaceProcessComplete: boolean = false; - - public constructor() { - this.vscodeSettings = vscode.workspace.getConfiguration('edk2code'); - this.workspaceConfig = this.readWpConfig(); - vscode.workspace.onDidChangeConfiguration(this.reloadVscodeSettings.bind(this)); - - } - - reloadVscodeSettings(event?: vscode.ConfigurationChangeEvent){ - this.vscodeSettings = vscode.workspace.getConfiguration('edk2code'); - } - - isWarningCppExtension(){ - return this.get("warningAboutCppExtension"); - } - - async setWarningCppExtension(value:boolean){ - await this.set("warningAboutCppExtension",value); - } - - isDiagnostics(){ - return this.get("enableDiagnostics"); - } - - reloadConfigFile(){ - this.workspaceConfig = this.readWpConfig(); - } - - getConfigFileUri(){ - return vscode.Uri.file(getEdkCodeFolderFilePath(this.settingsFileName)); - } - - private readWpConfig(){ - let settingsPath = getEdkCodeFolderFilePath(this.settingsFileName); - gDebugLog.trace(`Loading configuration from ${settingsPath}`); - if(existsEdkCodeFolderFile(this.settingsFileName)){ - - try { - return JSON.parse(readFile(settingsPath)); - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showErrorMessage(`${settingsPath} is corrupted: ${error}`); - return this.getCleanWpConfig(); - } - - }else{ - return this.getCleanWpConfig(); - } - } - - getWorkspaceConfig(): WorkspaceConfig { - return this.workspaceConfig; - } - - writeWorkspaceConfig(config:WorkspaceConfig){ - let data = JSON.stringify(config,null,4); - writeEdkCodeFolderFile(this.settingsFileName,data); - this.workspaceConfig = config; - } - - clearWpConfiguration(){ - this.workspaceConfig = this.getCleanWpConfig(); - // Mark workspace as not-yet-processed so the next loadConfig - // will build a temporary T-tree for fast file lookups. - this._workspaceProcessComplete = false; - } - - /** - * Returns `true` if the previous workspace processing completed - * successfully (i.e. packagePaths are fully populated). - */ - isWorkspaceProcessComplete(): boolean { - return this._workspaceProcessComplete; - } - - /** - * Mark the workspace processing as complete and dispose of the - * temporary file index so that normal `findFiles` is used again. - */ - setWorkspaceProcessComplete(): void { - this._workspaceProcessComplete = true; - if (this._fileIndex) { - this._fileIndex.dispose(); - this._fileIndex = null; - } - } - - /** - * Build the temporary T-tree file index if the workspace has not - * yet been fully processed (packagePaths not populated). - * This should be called at the beginning of workspace processing. - */ - async buildFileIndexIfNeeded(): Promise { - if (!this._workspaceProcessComplete) { - this._fileIndex = new TernarySearchTree(); - await this._fileIndex.buildFromWorkspace(); - } - } - - /** - * Returns the temporary file index if one is active, or `null` - * when the workspace is fully processed and findFiles should be - * used instead. - */ - getFileIndex(): TernarySearchTree | null { - return this._fileIndex; - } - - initConfigWatcher(){ - - this.configFileWatcher = vscode.workspace.createFileSystemWatcher(getEdkCodeFolderFilePath(this.settingsFileName)); - - // this.configFileWatcher.onDidCreate((uri) => { - // this.propertiesFile = uri; - // this.handleConfigurationChange(); - // }); - - // this.configFileWatcher.onDidDelete(() => { - // this.propertiesFile = null; - // this.resetToDefaultSettings(true); - // this.handleConfigurationChange(); - // }); - - this.configFileWatcher.onDidChange(() => { - this.handleConfigurationChange(); - }); - } - - setPanel(settingsPanel: SettingsPanel) { - this.settingsPanel = settingsPanel; - settingsPanel.configValuesChanged(() => this.saveConfigurationUI()); - } - - saveConfigurationUI(){ - - } - - handleConfigurationChange() { - let newConfig:WorkspaceConfig = this.readWpConfig(); - let reload = false; - if(this.workspaceConfig.dscPaths.toString() !== newConfig.dscPaths.toString()){ - reload = true; - } - if(this.workspaceConfig.buildDefines.toString() !== newConfig.buildDefines.toString()){ - reload = true; - } - this.workspaceConfig = this.readWpConfig(); - if(reload){ - askReloadFiles(); - } - } - - resetToDefaultSettings(arg0: boolean) { - throw new Error('Method not implemented.'); - } - - getCleanWpConfig():WorkspaceConfig{ - return {packagePaths:[], dscPaths:[], buildDefines:[]}; - } - - - - - - get(option: string) { - return this.vscodeSettings.get(option); - } - - async set(option: string, value: any) { - await this.vscodeSettings.update(option, value); - } - - getLogLevel(): LogLevel { - let logLevel: string = this.get("logLevel"); - switch (logLevel) { - case "None": - return LogLevel.none; - case "Error": - return LogLevel.error; - case "Warning": - return LogLevel.warning; - case "Info": - return LogLevel.info; - case "Verbose": - return LogLevel.verbose; - case "Debug": - return LogLevel.debug; - default: - return LogLevel.none; - break; - } - } - - async setBuildDefines(defines: Map) { - - let toSave: string[] = []; - for (const [key, value] of defines.entries()) { - // Normalize double backslashes to single to avoid over-escaping in JSON - toSave.push(`${key.trim()}=${value.trim().replace(/\\\\/g, '\\')}`); - } - this.workspaceConfig.buildDefines = toSave; - this.writeWorkspaceConfig(this.workspaceConfig); - - } - - async setBuildDefine(name: string, value: string) { - let buildDefines: string[] = this.workspaceConfig.buildDefines; - let toSave: string[] = []; - for (const def of buildDefines) { - if (!def.startsWith(`${name}=`)) { - toSave.push(def); - } - } - // Normalize double backslashes to single to avoid over-escaping in JSON - toSave.push(`${name}=${value.trim().replace(/\\\\/g, '\\')}`); - this.workspaceConfig.buildDefines = toSave; - this.writeWorkspaceConfig(this.workspaceConfig); - } - - getBuildDefines() { - let buildDefines: string[] = this.workspaceConfig.buildDefines; - - let buildDefinesObj: Map = new Map(); - for (const def of buildDefines) { - if(def.length === 0){continue;} - if (def.includes("=")) { - let values = def.split("="); - if (values.length !== 2) { continue; } - buildDefinesObj.set(values[0].trim(), values[1].trim()); - } else { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showErrorMessage(`Malformed define in setting: "${def}"`); - } - } - return buildDefinesObj; - } - - getBuildPackagePaths() { - let paths = this.workspaceConfig.packagePaths; - let retPaths = []; - for (const p of paths) { - if (path.isAbsolute(p)) { - retPaths.push(p); - } else { - retPaths.push(path.join(gWorkspacePath, p)); - } - } - return retPaths; - } - - - pushBuildPackagePaths(path:string) { - if(this.workspaceConfig.packagePaths.includes(path)){ - return; - } - // EDK2 build system does not allow spaces in PACKAGES_PATH entries - if(path.includes(' ')){ - return; - } - this.workspaceConfig.packagePaths.push(path); - this.writeWorkspaceConfig(this.workspaceConfig); - } - - async setBuildDscPaths(dscFiles: string[]) { - this.workspaceConfig.dscPaths = dscFiles; - this.writeWorkspaceConfig(this.workspaceConfig); - - } - - getBuildDscPaths() { - return this.workspaceConfig.dscPaths; - } - - getWorkspaceTreeFilters(): number[] | undefined { - return this.workspaceConfig.workspaceTreeFilters; - } - - setWorkspaceTreeFilters(filters: number[]): void { - this.workspaceConfig.workspaceTreeFilters = filters; - this.writeWorkspaceConfig(this.workspaceConfig); - } - - getIsGenIgnoreFile() { - return this.get("generateIgnoreFile"); - } - - getDelayToRefreshWorkspace() { - return this.get("delayToRefreshWorkspace"); - } - - getUseEdkCallHiearchy(){ - return this.get("useEdkCallHierarchy"); - } - - getExpandCircularOrDuplicateLibraries(){ - return this.get("ExpandCircularOrDuplicateLibraries"); - } - - getExtraIgnorePatterns() { - return this.get("extraIgnorePatterns"); - } - - getUseCscope() { - return this.get("useCscope"); - } - - getCscopeOverwritePath() { - return (this.get("cscopeOverwritePath")).trim(); - } - - getBuildToolchain(): string { - return process.platform === 'win32' ? "VS2019" : "GCC"; - } - - getBuildArch(): string { - return this.get("buildArch") || "X64"; - } - - getBuildTarget(): string { - return this.get("buildTarget") || "DEBUG"; - } - - getBuildExtraArgs(): string[] { - return this.get("buildExtraArgs") || []; - } - - getIsGenGuidXrefFile() { - return this.get("generateGuidXref"); - } - - getIsShowLanguageWarnings() { - return this.get("showEdk2LanguageWarnings"); - } - - getIsDimmUnusedLibraries() { - return this.get("dimUnusedLibraries"); - } - - async setDimmUnusedLibraries(value: boolean) { - await this.set("dimUnusedLibraries", value); - } - - async saveBuildConfig() { - let savePath = await vscode.window.showSaveDialog({ - defaultUri: vscode.Uri.file(gWorkspacePath), - filters: { - // eslint-disable-next-line @typescript-eslint/naming-convention - 'Json': ['json'], - }, - }); - if (savePath) { - let packages = this.getBuildPackagePaths(); - let dscs = this.getBuildDscPaths(); - let defines = this.getBuildDefines(); - - let definesList = []; - for (const [key, value] of defines) { - definesList.push(`${key}=${value}`); - } - - - let object = { - "includePaths": packages, - "dscs": dscs, - "defines": definesList - }; - fs.writeFileSync(savePath.fsPath, JSON.stringify(object, null, 2)); - } - } - - - -} \ No newline at end of file diff --git a/src/contextState/cmds.ts b/src/contextState/cmds.ts deleted file mode 100644 index 74923e4..0000000 --- a/src/contextState/cmds.ts +++ /dev/null @@ -1,712 +0,0 @@ -import { Uri } from "vscode"; -import * as vscode from 'vscode'; -import { rgSearch } from "../rg"; -import { delay, getCurrentWord, gotoFile, isWorkspacePath, listFilesRecursive, openTextDocument, pathCompare, profileEnd, profileStart, readLines, toPosix } from "../utils"; -import path = require("path"); -import * as fs from 'fs'; -import { edkWorkspaceTreeProvider, edkWorkspaceTreeView, gConfigAgent, gCscope, gDebugLog, gEdkWorkspaces, gExtensionContext, gMapFileManager, gPathFind, gWorkspacePath } from "../extension"; -import { glob } from "fast-glob"; -import { BuildFolder } from "../Languages/buildFolder"; -import { EdkWorkspace, InfDsc } from "../index/edkWorkspace"; -import { getParser, getParserForDocument } from "../edkParser/parserFactory"; -import { Edk2SymbolType } from "../symbols/symbolsType"; -import * as edkStatusBar from '../statusBar'; -import { SettingsPanel } from "../settings/settingsPanel"; -import { deleteEdkCodeFolder, existsEdkCodeFolderFile } from "../edk2CodeFolder"; -import { infoMissingCompileInfo } from "../ui/messages"; -import { checkCppConfiguration } from "../cppProviders/cppUtils"; -import { buildEdk2Workspace as buildEdk2WorkspaceImpl } from "../buildEdk2"; -import { DocumentSymbolItem, WorkspaceRootItem, WorkspaceTreeNode } from "../workspaceTree/WorkspaceTreeProvider"; - - export async function buildEdk2Workspace() { - await buildEdk2WorkspaceImpl(); - } - - /** - * Build command launched from the workspace tree. - * - On a WorkspaceRootItem: builds the whole DSC. - * - On a DocumentSymbolItem (library/module): builds just that module via `-m`. - */ - export async function buildFromTree(node: WorkspaceTreeNode | undefined) { - if (!node) { - await buildEdk2WorkspaceImpl(); - return; - } - // Keep the node selected so the user knows which module will be built - edkWorkspaceTreeView.reveal(node, { select: true, focus: false }); - if (node instanceof WorkspaceRootItem) { - await buildEdk2WorkspaceImpl({ dscPath: node.workspace.mainDsc.fsPath }); - return; - } - if (node instanceof DocumentSymbolItem) { - // Walk up parent chain to find the owning WorkspaceRootItem (DSC). - let cur: WorkspaceRootItem | DocumentSymbolItem | undefined = node.parent; - while (cur && !(cur instanceof WorkspaceRootItem)) { - cur = (cur as DocumentSymbolItem).parent; - } - const dscPath = cur instanceof WorkspaceRootItem ? cur.workspace.mainDsc.fsPath : undefined; - - // Extract the INF path directly from the DSC text line. - // textLine already resolves parser-level defines; we also call - // gEdkWorkspaces.replaceDefines() for workspace-level variables - // like $(SOME_VARIABLE) that might still be present. - let modulePath: string | undefined; - try { - const sym: any = node.symbol; - - if (sym.type === Edk2SymbolType.dscLibraryDefinition) { - void vscode.window.showWarningMessage( - 'Libraries cannot be built standalone with `build -m`. Only components (modules) listed in [Components] can be built individually.' - ); - return; - } - - const textLine: string = sym.textLine || ''; - if (sym.type === Edk2SymbolType.dscModuleDefinition) { - // Format: "Path/To/Module.inf" possibly followed by " { ... }" - const rawPath = textLine.replace(/\s*\{.*/, '').trim(); - if (rawPath) { - modulePath = await gEdkWorkspaces.replaceDefines(node.fileUri, rawPath); - } - } - } catch { - // ignore - } - if (!modulePath) { - void vscode.window.showErrorMessage('Could not resolve INF path for selected node.'); - return; - } - await buildEdk2WorkspaceImpl({ dscPath, modulePath }); - return; - } - // Unknown node type – fall back to generic build. - await buildEdk2WorkspaceImpl(); - } - - let discoveredBuildFolders: string[] = []; - let buildFolderScanTimer: NodeJS.Timeout | undefined; - let scanInProgressPromise: Promise | undefined; - - /** - * Searches for BuildOptions files in the given search path. - * Returns an array of directory paths that contain BuildOptions files. - */ - export async function findBuildOptionsFolders(searchPath: string): Promise { - let lookPath = toPosix(path.join(searchPath, "**", "BuildOptions")); - let buildInfoFolders = await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: "Looking for compile info", - cancellable: true - }, async (progress, reject) => { - return glob(lookPath); - }); - - return buildInfoFolders.map((x) => { - return path.parse(String(x)).dir; - }); - } - - /** - * Periodically scans the workspace for BuildOptions folders. - * When found, sets a context key so the welcome view can show the discovery action. - */ - export function startBuildFolderScan(intervalMs: number = 600000) { - stopBuildFolderScan(); - // Run immediately once - void scanWorkspaceForBuildFolders(); - buildFolderScanTimer = setInterval(() => { - void scanWorkspaceForBuildFolders(); - }, intervalMs); - } - - export function stopBuildFolderScan() { - if (buildFolderScanTimer) { - clearInterval(buildFolderScanTimer); - buildFolderScanTimer = undefined; - } - } - - async function scanWorkspaceForBuildFolders() { - if (scanInProgressPromise) { return scanInProgressPromise; } - scanInProgressPromise = doScanWorkspace(); - try { - await scanInProgressPromise; - } finally { - scanInProgressPromise = undefined; - } - } - - async function doScanWorkspace() { - try { - let lookPath = toPosix(path.join(gWorkspacePath, "**", "BuildOptions")); - let results = await glob(lookPath); - let folders = results.map((x) => path.parse(String(x)).dir); - - if (folders.length > 0) { - discoveredBuildFolders = folders; - await vscode.commands.executeCommand('setContext', 'edk2code.buildFoldersFound', true); - } else { - discoveredBuildFolders = []; - await vscode.commands.executeCommand('setContext', 'edk2code.buildFoldersFound', false); - } - } catch (error) { - gDebugLog.error(`scanWorkspaceForBuildFolders: ${error}`); - } - } - - /** - * Manually triggers discovery of build folders in the workspace. - * Shows a discovering state in the view while scanning. - */ - export async function discoverBuildFolders() { - await vscode.commands.executeCommand('setContext', 'edk2code.isDiscovering', true); - try { - await scanWorkspaceForBuildFolders(); - } finally { - await vscode.commands.executeCommand('setContext', 'edk2code.isDiscovering', false); - } - } - - /** - * Called when user clicks "Use discovered folders" in the welcome view. - * Shows the discovered build folders and lets the user pick which ones to use. - */ - export async function useDiscoveredBuildFolders() { - if (discoveredBuildFolders.length === 0) { - void vscode.window.showInformationMessage("No build folders discovered yet."); - return; - } - - var options: vscode.QuickPickItem[] = []; - for (const foundPath of discoveredBuildFolders) { - let splitPath = foundPath.split(path.posix.sep); - options.push({ - label: splitPath[splitPath.length - 2], - description: "", - detail: foundPath, - }); - } - - let selectedOptions = await vscode.window.showQuickPick(options, { title: "Select build folders to use", matchOnDescription: true, matchOnDetail: true, canPickMany: true }); - if (selectedOptions === undefined) { return; } - - let selectedFolders: string[] = []; - for (const op of selectedOptions) { - if (op.detail) { - selectedFolders.push(op.detail); - } - } - - if (selectedFolders.length > 0) { - await vscode.commands.executeCommand('setContext', 'edk2code.isLoading', true); - await rebuildIndexDatabase(selectedFolders); - await vscode.commands.executeCommand('setContext', 'edk2code.isLoading', false); - } - } - - export async function rebuildIndexDatabase(preselectedFolders?: string[]){ - gDebugLog.trace("Rebuilding index database"); - - let selectedFolders: string[] = []; - - if (preselectedFolders && preselectedFolders.length > 0) { - // Use pre-discovered folders directly - selectedFolders = preselectedFolders; - } else { - // Pick build folder interactively - let buildPath = await vscode.window.showOpenDialog({ - defaultUri: vscode.Uri.file(gWorkspacePath), canSelectFiles: false, canSelectFolders: true, canSelectMany: false, - filters: { - // eslint-disable-next-line @typescript-eslint/naming-convention - 'BuildFolder': ['Build'], - }, - title: "Select EDK build folder" - }); - - // If build folder picked - if (buildPath) { - // Check if its part of workspace - if (isWorkspacePath(buildPath[0].fsPath)) { - let configPath = buildPath[0].fsPath; - - let buildInfoFolders = await findBuildOptionsFolders(configPath); - - // Build Options not found this is not a build folder - if (buildInfoFolders.length === 0) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showErrorMessage(`Build data was not found in selected folder`); - return; - } - - // Show options for builds - var options: vscode.QuickPickItem[] = []; - for (const foundPath of buildInfoFolders) { - let splitPath = foundPath.split(path.posix.sep); - - options.push({ - label: splitPath[splitPath.length - 2], - description: "", - detail: foundPath, - }); - } - - let selectedOptions = await vscode.window.showQuickPick(options, { title: "Select build", matchOnDescription: true, matchOnDetail: true, canPickMany: true }); - if (selectedOptions === undefined) { return; } - - for (const op of selectedOptions) { - if (op.detail) { - selectedFolders.push(op.detail); - } - } - } else { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showErrorMessage(`${buildPath[0].fsPath} its outside workspace`); - return; - } - } else { - return; - } - } - - if (selectedFolders.length === 0) { return; } - - gDebugLog.trace("Loading from build"); - - let buildFolder = new BuildFolder(selectedFolders); - let buildData = await buildFolder.getBuildOptions(); - if (buildData) { - gDebugLog.trace("Delete workspace files"); - // await gEdkDatabase.clearWorkspace(); - deleteEdkCodeFolder(); - gConfigAgent.clearWpConfiguration(); - await gConfigAgent.setBuildDefines(buildData.buildDefines); - await gConfigAgent.setBuildDscPaths(buildData.dscFiles); - buildFolder.copyCompileInfoToRoot(); - - // If cscope.file is not generated, then calculate files based on dsc parsing - if(existsEdkCodeFolderFile(".missing")){ - infoMissingCompileInfo(); - await reloadSymbols(); - }else{ - await checkCppConfiguration(); - await gCscope.reload(); - } - - // Generate .ignore if setting is set and .ignore doesnt exists - if (gConfigAgent.getIsGenIgnoreFile()) { - await genIgnoreFile(); - } - - await buildFolder.copyMapFilesList(); - gMapFileManager.load(); - - void vscode.window.showInformationMessage("Build data loaded"); - - await gEdkWorkspaces.loadConfig(); - } - } - - export async function unloadWorkspace() { - const confirm = await vscode.window.showWarningMessage( - "Are you sure you want to unload the workspace? This will remove all indexed data.", - { modal: true }, - "Unload" - ); - if (confirm !== "Unload") { return; } - - gDebugLog.trace("Unloading workspace"); - deleteEdkCodeFolder(); - gConfigAgent.clearWpConfiguration(); - gEdkWorkspaces.workspaces = []; - edkWorkspaceTreeProvider.refresh(); - void vscode.window.showInformationMessage("Workspace unloaded"); - } - - export async function rescanIndex() { - gConfigAgent.reloadConfigFile(); - await reloadSymbols(); - // Generate .ignore if setting is set and .ignore doesnt exists - if (gConfigAgent.getIsGenIgnoreFile()) { - await genIgnoreFile(); - } - } - - export async function openFile() { - let wps = gEdkWorkspaces.workspaces; - var itemsOption: vscode.QuickPickItem[] = []; - if(wps.length){ - for (const wp of wps) { - for(const s of wp.getFilesList()){ - itemsOption.push({ - label: `$(file) ${path.basename(s)}`, - description: s - }); - } - } - } - await vscode.window.showQuickPick(itemsOption, { title: "Files on workspaces", matchOnDescription: true, matchOnDetail: true }).then(async option => { - if (option !== undefined) { - let path = await gPathFind.findPath(option.description!); - // await vscode.commands.executeCommand('editor.action.goToLocations', vscode.window.activeTextEditor?.document.uri, vscode.window.activeTextEditor?.selection.active, path , "gotoAndPeek", "Not found"); - if(path.length){ - await vscode.commands.executeCommand("edk2code.gotoFile", path[0].uri); - } - - } - }); - } - export async function openLib() { - let wps = gEdkWorkspaces.workspaces; - var itemsOption: vscode.QuickPickItem[] = []; - if(wps.length){ - for (const wp of wps) { - for(const s of wp.filesLibraries){ - let filePath = await gPathFind.findPath(s.path); - if(filePath.length){ - itemsOption.push({ - label: `$(file) ${path.basename(s.path)}`, - description: filePath[0].uri.fsPath - }); - } - } - } - } - await vscode.window.showQuickPick(itemsOption, { title: "Libraries on workspaces", matchOnDescription: true, matchOnDetail: true }).then(async option => { - if (option !== undefined) { - await vscode.commands.executeCommand("edk2code.gotoFile", vscode.Uri.file(option.description!)).then(() => { - - } - ); - } - }); - } - export async function openModule() { - let wps = gEdkWorkspaces.workspaces; - var itemsOption: vscode.QuickPickItem[] = []; - if(wps.length){ - for (const wp of wps) { - for(const s of wp.filesModules){ - let filePath = await gPathFind.findPath(s.path); - if(filePath.length){ - itemsOption.push({ - label: `$(file) ${path.basename(s.path)}`, - description: filePath[0].uri.fsPath - }); - } - - } - } - } - await vscode.window.showQuickPick(itemsOption, { title: "Modules on workspaces", matchOnDescription: true, matchOnDetail: true }).then(async option => { - if (option !== undefined) { - await vscode.commands.executeCommand("edk2code.gotoFile", vscode.Uri.file(option.description!)).then(() => { - - } - ); - } - }); - } - export async function gotoDefinitionCscope(fileUri:vscode.Uri) { - let currentWord = getCurrentWord(); - if(currentWord !== undefined){ - - // Filter results to only show files used in compilation - let filteredLocations:vscode.Location[] = []; - - // First look using Cscope - filteredLocations = await gCscope.getDefinitionPositions(currentWord.word); - - if(filteredLocations.length === 0){ - let allLocations:vscode.Location[] = await vscode.commands.executeCommand('vscode.executeDefinitionProvider', currentWord.uri, currentWord.range.end); - for (const loc of allLocations) { - - let isFileUsed = await gEdkWorkspaces.isFileInUse(loc.uri); - if(isFileUsed){ - filteredLocations.push(loc); - } - } - } - - await vscode.commands.executeCommand('editor.action.goToLocations', currentWord.uri, currentWord.range.end, filteredLocations, "gotoAndPeek", "Not found"); - - } - } - export function gotoDefinitionInput(): void { - throw new Error("Method not implemented."); - } - - export async function gotoInf(fileUri: Uri) { - let locations: vscode.Location[] = []; - - let wps = await gEdkWorkspaces.getWorkspace(fileUri); - if(wps.length){ - for (const wp of wps) { - locations = await wp.getInfReference(fileUri); - if(locations.length){ - await vscode.commands.executeCommand('editor.action.goToLocations', vscode.window.activeTextEditor?.document.uri, vscode.window.activeTextEditor?.selection.active, locations, "gotoAndPeek", "Not found"); - await edkWorkspaceTreeProvider.revealInfInTree(locations[0].uri, edkWorkspaceTreeView); - } - } - }else{ - // Skip if source hasn't been indexed. Just make a search query - let fileName = path.basename(fileUri.fsPath); - let folderPath = path.dirname(fileUri.fsPath); - - let tempLocations = await rgSearch(`\\b${fileName}\\b`, ["*.inf"],[],true); - for (const l of tempLocations) { - // Check the INF file is relative to the source file - if (!path.relative(path.dirname(l.uri.fsPath), folderPath).includes("..")) { - locations.push(l); - } - } - await vscode.commands.executeCommand('editor.action.goToLocations', vscode.window.activeTextEditor?.document.uri, vscode.window.activeTextEditor?.selection.active, locations, "gotoAndPeek", "Not found"); - - } - - } - - export async function gotoDscDeclaration(fileUri: Uri) { - - let fileName = path.basename(fileUri.fsPath); - - return await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: "Looking for references...", - cancellable: true - }, async (progress, reject) => { - - let wps = await gEdkWorkspaces.getWorkspace(fileUri); - let locations; - if(wps.length){ - let dscDeclarations: InfDsc[] = []; - for (const wp of wps) { - dscDeclarations = dscDeclarations.concat(await wp.getDscDeclaration(fileUri)); - } - locations = dscDeclarations.map((x) => {return x.location;}); - - - }else{ - locations = await rgSearch(`-i --regexp ".*?\\b${fileName}\\b"`, ["*.dsc","*.dsc.inc"]); - - } - await vscode.commands.executeCommand('editor.action.goToLocations', vscode.window.activeTextEditor?.document.uri, vscode.window.activeTextEditor?.selection.active, locations , "gotoAndPeek", "Not found"); - - - }); - } - - - - export async function gotoDscInclusion(fileUri: Uri) { - - let fileName = path.basename(fileUri.fsPath); - - return await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: "Looking for references...", - cancellable: true - }, async (progress, reject) => { - - let locations:vscode.Location[] = []; - let wps = await gEdkWorkspaces.getWorkspace(fileUri); - if(wps.length){ - for (const wp of wps) { - locations = locations.concat(await wp.getIncludeReference(fileUri)); - } - if(locations.length){ - await vscode.commands.executeCommand('editor.action.goToLocations', vscode.window.activeTextEditor?.document.uri, vscode.window.activeTextEditor?.selection.active, locations , "gotoAndPeek", "Not found"); - return; - } - } - - locations = await rgSearch(`-i --regexp "\!include\\s+.*?\\b${fileName}\\b"`, ["*.dsc"," *.dsc.inc","*.fdf","*.fdf.inc"]); - await vscode.commands.executeCommand('editor.action.goToLocations', vscode.window.activeTextEditor?.document.uri, vscode.window.activeTextEditor?.selection.active, locations , "gotoAndPeek", "Not found"); - - - - - }); - - - - } - - - let proccesedInfFiles:Set = new Set(); - - export async function reloadSymbols(){ - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: "Indexing C files in workspace", - cancellable: true - }, async (progress, reject) => { - await gEdkWorkspaces.loadConfig(); - edkWorkspaceTreeProvider.refresh(); - let filesList:string[] = []; - let decList:string[] = []; - let hFiles:string[] = []; - - edkStatusBar.pushText("Index source files..."); - edkStatusBar.setWorking(); - proccesedInfFiles = new Set(); - - let wpInfFiles:InfDsc[] = []; - // Grab all inf files in all workspaces - for (const wp of gEdkWorkspaces.workspaces) { - if(reject.isCancellationRequested){break;} - for (const dsc of wp.dscList()) { - if(reject.isCancellationRequested){break;} - filesList.push(dsc); - } - wpInfFiles = wpInfFiles.concat(wp.filesLibraries.concat(wp.filesModules)); - } - - const increment = 100/wpInfFiles.length; - for (const lib of wpInfFiles) { - progress.report({message:"Parsing INF files",increment:increment}); - if(reject.isCancellationRequested){break;} - // get all sources - try { - let p = await gPathFind.findPath(lib.path); - if(p.length){ - // Skip inf files that have been proccesed - if(proccesedInfFiles.has(p[0].uri.fsPath)){ - continue; - }else{ - proccesedInfFiles.add(p[0].uri.fsPath); - } - let document = await openTextDocument(p[0].uri); - let parser = await getParserForDocument(document); - if(parser){ - - // Parse source files - let sources = parser.getSymbolsType(Edk2SymbolType.infSource); - filesList.push(parser.document.fileName); - for (const source of sources) { - if(reject.isCancellationRequested){break;} - filesList.push(await source.getValue()); - } - - // Parse DEC files - let decs = parser.getSymbolsType(Edk2SymbolType.infPackage); - for (const dec of decs) { - if(reject.isCancellationRequested){break;} - let decValue = await dec.getValue(); - if(decList.includes(decValue) || decValue === ""){continue;} - decList.push(decValue); - let decPath = await gPathFind.findPath(decValue); - if(decPath.length){ - let decDoc = await openTextDocument(decPath[0].uri); - let decParser = await getParserForDocument(decDoc); - if(decParser){ - let decIncludes = decParser.getSymbolsType(Edk2SymbolType.decInclude); - for (const decInclude of decIncludes) { - if(reject.isCancellationRequested){break;} - let decIncludedPath = await decInclude.getKey(); - let sourcesIncluded = await listFilesRecursive(decIncludedPath); - for (const sourceIncluded of sourcesIncluded) { - if(reject.isCancellationRequested){break;} - if(sourceIncluded.toLowerCase().endsWith(".h")){ - let sourceFullPath = path.join(decIncludedPath, sourceIncluded); - if(!hFiles.includes(sourceFullPath)){ - hFiles.push(sourceFullPath); - } - } - } - } - } - } - - // For each new DEC file, check its "Include" section and add h files - - } - } - } - } catch (error) { - gDebugLog.error(`reloadSymbols: ${error}`); - } - } - - - progress.report({message:"Running Cscope"}); - await delay(200); // Delay to update GUI - filesList = filesList.concat(decList).concat(hFiles); - gCscope.writeCscopeFile(filesList); - await gCscope.reload(); - edkStatusBar.clearWorking(); - edkStatusBar.popText(); - - - - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showInformationMessage(`Index complete: ${gCscope.readCscopeFile().length} files found`); - }); - } - - /** - * Creates .ignore file. this will check for this.getFilesInUse() and will ignore all the - * files that are not used - * @returns - */ - async function genIgnoreFile() { - - return await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: "Creating .ignore file", - cancellable: true - }, async (progress, reject) => { - - gDebugLog.info("Generating .ignore file"); - let cscopeFilesList = gCscope.readCscopeFile(); - gDebugLog.info(`genIgnoreFile: cscope list has ${cscopeFilesList.length} entries`); - let filesSet = new Set(); - let filesExtensions = new Set(); - for (const cscopeFile of cscopeFilesList) { - let progFileUpper = cscopeFile.toUpperCase(); - filesSet.add(progFileUpper); - filesExtensions.add(path.extname(progFileUpper)); - } - gDebugLog.info(`genIgnoreFile: tracking ${filesExtensions.size} extensions: ${[...filesExtensions].join(", ")}`); - - gDebugLog.info(`genIgnoreFile: listing workspace files under ${gWorkspacePath}`); - let globFilesList = (await listFilesRecursive(gWorkspacePath)).map(f => path.join(gWorkspacePath, f)); - gDebugLog.info(`genIgnoreFile: workspace file scan returned ${globFilesList.length} files`); - let ignoreList = []; - - // Add extra ignore patterns - let extraIgnores = gConfigAgent.getExtraIgnorePatterns(); - gDebugLog.info(`genIgnoreFile: ${extraIgnores.length} extra ignore patterns from config`); - for (const extraIgnore of extraIgnores) { - ignoreList.push(extraIgnore.trim()); - } - - let posixWorkspacePath = toPosix(gWorkspacePath); - gDebugLog.info(`Cscope files found: ${filesSet.size}`); - - let reportCount = 0; - for (const globFile of globFilesList) { - // Just ignore EDK files - const globFileUpperCase = globFile.toUpperCase(); - const extension = path.extname(globFileUpperCase); - if (filesExtensions.has(extension) && !filesSet.has(globFileUpperCase)) { - if (++reportCount % 100 === 0) { - progress.report({ message: globFile }); - } - ignoreList.push(toPosix(path.relative(posixWorkspacePath, globFile))); - } - } - gDebugLog.info(`genIgnoreFile: ${ignoreList.length} entries written to .ignore (${reportCount} files ignored)`); - const ignoreFilePath = path.join(gWorkspacePath, ".ignore"); - fs.writeFileSync(ignoreFilePath, ignoreList.join("\n")); - gDebugLog.info(`genIgnoreFile: .ignore written to ${ignoreFilePath}`); - - }); - - } - -export async function openWpConfigGui() { - SettingsPanel.render(gExtensionContext.extensionUri, gConfigAgent); -} -export async function openWpConfigJson() { - await gotoFile(gConfigAgent.getConfigFileUri()); -} \ No newline at end of file diff --git a/src/cppProviders/clangd.ts b/src/cppProviders/clangd.ts deleted file mode 100644 index 24f29b0..0000000 --- a/src/cppProviders/clangd.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as vscode from 'vscode'; -import { CppProvider } from './cppProvider'; -import { updateCompilesCommandCpp } from '../ui/messages'; - -export class ClangdProvider extends CppProvider { - extensionId = "llvm-vs-code-extensions.vscode-clangd"; - isCpptoolsInstalled(): boolean { - return vscode.extensions.getExtension(this.extensionId) !== undefined; - } - - async validateConfiguration(): Promise { - const expectedArgument = "--compile-commands-dir=${workspaceFolder}/.edkCode/"; - const clangdConfiguration = vscode.workspace.getConfiguration('clangd'); - const clangdArguments = clangdConfiguration.get('arguments') || []; - const existingIndex = clangdArguments.findIndex(arg => arg.startsWith('--compile-commands-dir=')); - let updatedArguments = [...clangdArguments]; - if (existingIndex === -1) { - let update = await updateCompilesCommandCpp(); - if (update) { - updatedArguments.push(expectedArgument); - await clangdConfiguration.update('arguments', updatedArguments, vscode.ConfigurationTarget.Workspace); - } - } else if (!clangdArguments.includes(expectedArgument)) { - let update = await updateCompilesCommandCpp(); - if (update) { - updatedArguments[existingIndex] = expectedArgument; - await clangdConfiguration.update('arguments', updatedArguments, vscode.ConfigurationTarget.Workspace); - } - } - - return true; - } -} \ No newline at end of file diff --git a/src/cppProviders/cppProvider.ts b/src/cppProviders/cppProvider.ts deleted file mode 100644 index 2deedf6..0000000 --- a/src/cppProviders/cppProvider.ts +++ /dev/null @@ -1,9 +0,0 @@ - - -export abstract class CppProvider { - - abstract extensionId: string; - abstract isCpptoolsInstalled(): boolean; - abstract validateConfiguration(): Promise; -} - diff --git a/src/cppProviders/cppUtils.ts b/src/cppProviders/cppUtils.ts deleted file mode 100644 index 80673cd..0000000 --- a/src/cppProviders/cppUtils.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as vscode from 'vscode'; - -import { gDebugLog } from '../extension'; -import * as fs from 'fs'; -import { infoMissingCppExtension } from '../ui/messages'; -import { closeFileIfOpened, delay } from '../utils'; -import { CppProvider } from './cppProvider'; -import { MsCppProvider } from './msCpp'; -import { ClangdProvider } from './clangd'; - - - -export function getCppProvider(): CppProvider|null { - let provider:CppProvider; - - - provider = new MsCppProvider(); - if (provider.isCpptoolsInstalled()){ - return provider; - } - - provider = new ClangdProvider(); - if (provider.isCpptoolsInstalled()){ - return provider; - } - - return null; -} - - -export async function checkCppConfiguration(){ - // Check if CPP extesion is installed - - const cppProvider = getCppProvider(); - - if(cppProvider === null){ - infoMissingCppExtension(); - return; - } - - await cppProvider.validateConfiguration(); - - -} - - - - - - diff --git a/src/cppProviders/msCpp.ts b/src/cppProviders/msCpp.ts deleted file mode 100644 index 978379e..0000000 --- a/src/cppProviders/msCpp.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as vscode from 'vscode'; -import { CppProvider } from './cppProvider'; -import * as fs from 'fs'; -import {closeFileIfOpened, delay } from '../utils'; -import { gDebugLog, gWorkspacePath } from '../extension'; -import path = require("path"); -import { updateCompilesCommandCpp } from '../ui/messages'; - -export class MsCppProvider extends CppProvider { - extensionId = "ms-vscode.cpptools"; - fixFile: Boolean|undefined = undefined; - - async isFixFile(): Promise { - if (this.fixFile === undefined){ - let update = await updateCompilesCommandCpp(); - this.fixFile = update; - } - return this.fixFile; - } - - isCpptoolsInstalled(): boolean { - return vscode.extensions.getExtension(this.extensionId) !== undefined; - } - - async validateConfiguration(): Promise { - - if (vscode.workspace.workspaceFile !== undefined){ - // Don't try to fix CPP if the workspace is not a folder - return true; - } - - if(!this.isCppPropertiesFile()){ - if(!await this.isFixFile()){ - return true; - } - await this.touchCppPropertiesFile(); // Asks CPP extension to create the file - } - - let retries = 30; - while(retries){ - if(await this.fixCppPropertiesFile()){ - break; - } - await delay(100); - retries--; - } - return true; - } - - private async touchCppPropertiesFile(){ - await vscode.commands.executeCommand('C_Cpp.ConfigurationEditJSON'); - } - - private getCppPropertiesPath(){ - let cCppPropertiesPath = path.join(gWorkspacePath, ".vscode", "c_cpp_properties.json"); - return cCppPropertiesPath; - } - - async fixCppPropertiesFile(){ - if(this.isCppPropertiesFile()){ - try { - - await closeFileIfOpened(this.getCppPropertiesPath()); - - let cProperties = JSON.parse(fs.readFileSync(this.getCppPropertiesPath()).toString()); - const expectedPath = path.join("${workspaceFolder}", ".edkCode", "compile_commands.json"); - const commandsPath = cProperties["configurations"][0]["compileCommands"]; - gDebugLog.debug(`cCppPropertiesPath: ${commandsPath}`); - gDebugLog.debug(`expectedPath: ${expectedPath}`); - if(commandsPath !== expectedPath){ - let update = await this.isFixFile(); - if(!update){ - return true; - } - cProperties["configurations"][0]["compileCommands"] = expectedPath; - fs.writeFileSync(this.getCppPropertiesPath(), JSON.stringify(cProperties,null,4)); - } - - } catch (error) { - gDebugLog.error(`Error fixing c_cpp_properties.json: ${error}`); - } - return true; - } - return false; - } - - private isCppPropertiesFile(){ - if (fs.existsSync(this.getCppPropertiesPath())) { - return true; - } - return false; - } -} - diff --git a/src/cscope.ts b/src/cscope.ts deleted file mode 100644 index a42f6ef..0000000 --- a/src/cscope.ts +++ /dev/null @@ -1,355 +0,0 @@ -import * as fs from 'fs'; -import path = require('path'); -import * as vscode from 'vscode'; -import { gConfigAgent, gCscope, gDebugLog, gEdkWorkspaces } from './extension'; -import { exec, execWindow, getStaticPath, normalizePath, readLines, toPosix } from './utils'; -import { execSync } from 'child_process'; -import * as edkStatusBar from './statusBar'; -import { getEdkCodeFolderFilePath, getEdkCodeFolderPath } from './edk2CodeFolder'; -import { Debouncer } from './debouncer'; - -/* -cscope -R -L -2 ".*" | awk -F ' ' '{print $2 "#" $1}' | sort | uniq -The command cscope -R -L -2 ".*" will output functions called by any function (see explanation of the options below). For each reference found, cscope outputs a line consisting of the file name, function name, line number, and line text, separated by spaces. -Use awk to extract the function name $2 and file name $1 separated by #. Change $2, $1 and the separator # if you need other output fields or separator. -Sort the output with sort. -Get unique items with uniq. -cscope options (see http://cscope.sourceforge.net/cscope_man_page.html): - --R Recurse subdirectories for source files. - --L Do a single search with line-oriented output when used with the -num pattern option. - --2 ".*" Go to input field num (here 0-based field 2) and find pattern (here .* for all). You can see the input fields in cscope's screen mode. This may vary depending on the version you are using. The fields for version 15.8a under debian are: - -0: Find this C symbol: -1: Find this global definition: -2: Find functions called by this function: -3: Find functions calling this function: -4: Find this text string: -5: Change this text string: -6: Find this egrep pattern: -7: Find this file: -8: Find files #including this file: -*/ -export enum CscopeCmd{ - findSymbol= "0", - findGlobalDef = "1", - findCallee = "2", - findCallers = "3", - findText = "4", - findEgrep = "6" - -} - - -export class FuncInfo -{ - public name:string; - // public type:string; - public line:number; - public file:string; - public snipped:string; - public searchTerm: string; - public end:number; - - constructor(name:string, line:number, file:string, snipped:string, searchTerm:string){ - this.searchTerm = searchTerm; - this.name = name; - this.line = line; - this.file = file; - this.snipped = snipped; - this.end = 0; - } - -} - - -export class Cscope { - cscopePath:string = ""; - cscopeInstalled = false; - - public constructor() { - let cscopeOverwritePath = gConfigAgent.getCscopeOverwritePath(); - - if(cscopeOverwritePath === ""){ - if (process.platform === 'win32'){ - this.cscopePath = getStaticPath("cscope.exe"); - }else{ - this.cscopePath = "cscope"; - } - }else{ - this.cscopePath = cscopeOverwritePath; - } - - - var command = `${this.cscopePath} -V`; - - try { - let result = execSync(command); - gDebugLog.info(result.toString()); - this.cscopeInstalled = true; - } catch (error) { - gDebugLog.error("Cscope not available in the system"); - this.cscopeInstalled = false; - } - - } - -/** - * Check if a file is included in the cscope.files list. - * - * This function checks if the given file path is included in the cscope.files list, - * which contains a list of files used by the Cscope tool for symbol lookup. - * - * @param filePath filePath The file path to check. - * - * @return True if the file is included in the cscope.files list, false otherwise. - */ - includesFile(filePath:vscode.Uri){ - let lines = this.readCscopeFile(); - for (const line of lines) { - if(filePath.fsPath.toLowerCase() === line.toLowerCase()){ - return true; - } - } - return false; - } - - showCscopeErrorMessage(){ - void vscode.window.showErrorMessage("Cscope not available in the system. Check help for install", "Help").then(async selection => { - if (selection === "Help"){ - await vscode.env.openExternal(vscode.Uri.parse( - 'https://intel.github.io/Edk2Code/getting_started/#cscope-installation-windowslinux')); - } - }); - } - - existCscopeFile(){ - - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - return fs.existsSync(cscopeFilesPath); - } - - writeCscopeFile(fileList:string[]){ - if(!gConfigAgent.getUseCscope()){ return; } - if(fileList.length === 0){ - return; - } - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - // Cscope.files uses forwardslash format for path - // Append " to the path to avoid issues with spaces - // Resolve all paths to OS format - let cscopeFiles = fileList.map((x)=>{return '"' + path.resolve(x.replaceAll("/",path.sep)) + '"';}).join("\n"); - fs.writeFileSync(cscopeFilesPath,cscopeFiles); - } - - readCscopeFile():string[]{ - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - let lines = readLines(cscopeFilesPath); - // Format line to match OS path - return lines.map((x)=>{return path.resolve(x.replaceAll('"',''));}); - } - - removeFiles() { - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - fs.rmSync(cscopeFilesPath, {force:true}); - - let cscopeOutPath = getEdkCodeFolderFilePath("cscope.out"); - fs.rmSync(cscopeOutPath, {force:true}); - - } - - - - - async reload(progressWindow=false){ - gDebugLog.info("CSCOPE reload database"); - if(!gConfigAgent.getUseCscope()){ - gDebugLog.info("CSCOPE is disabled by setting"); - return; - } - if(!this.cscopeInstalled){ - this.showCscopeErrorMessage(); - return; - } - edkStatusBar.pushText("Loading Cscope..."); - edkStatusBar.setWorking(); - if(this.existCscopeFile()){ - if(progressWindow){ - await execWindow(`"${this.cscopePath}" -Rb`, getEdkCodeFolderPath(), "Reload cscope database"); - }else{ - await exec(`"${this.cscopePath}" -Rb`, getEdkCodeFolderPath()); - } - } - edkStatusBar.popText(); - edkStatusBar.clearWorking(); - } - - async getCaller(text:string){ - if(!gConfigAgent.getUseCscope()){ return []; } - let result = await this.cscopeCommandWindow(text, CscopeCmd.findCallers, "Looking callers"); - let temp = this.parseResult(result, text); - return temp; - } - - async getCallee(text:string){ - if(!gConfigAgent.getUseCscope()){ return []; } - let result = await this.cscopeCommandWindow(text, CscopeCmd.findCallee, "Looking callees"); - return this.parseResult(result, text); - } - - async search(text:string){ - if(!gConfigAgent.getUseCscope()){ return []; } - let result = await this.cscopeCommandWindow(text, CscopeCmd.findEgrep, "Searching"); - let searchResult = this.parseResult(result, text); - - let returnValues:vscode.Location[] = []; - - for (const res of searchResult) { - let pos = new vscode.Position(res.line, 0); - returnValues.push( - new vscode.Location(vscode.Uri.file(res.file), new vscode.Range(pos, pos)) - ); - } - return returnValues; - - } - - async getDefinitionPositions(text:string, showWindows:boolean=true){ - if(!gConfigAgent.getUseCscope()){ return []; } - - let windDescription = "Looking for definition"; - if(!showWindows){ - // Remove description so window is not shown - windDescription = ""; - } - - let result = await this.cscopeCommandWindow(text, CscopeCmd.findGlobalDef, "Looking for definition"); - let searchResult = this.parseResult(result, text); - - let returnValues:vscode.Location[] = []; - - for (const res of searchResult) { - let pos = new vscode.Position(res.line, 0); - returnValues.push( - new vscode.Location(vscode.Uri.file(res.file), new vscode.Range(pos, pos)) - ); - } - return returnValues; - - } - - async cscopeCommand(text:string, cmdType:CscopeCmd){ - if(!this.cscopeInstalled){ - this.showCscopeErrorMessage(); - return ""; - } - var command = `${this.cscopePath} -d -L${cmdType}${text}`; - let result = await exec(command, getEdkCodeFolderPath()); - return result; - } - - async cscopeCommandWindow(text:string, cmdType:CscopeCmd, textWindow:string=""){ - let cscopeOutPath = getEdkCodeFolderFilePath("cscope.out"); - - if(!this.cscopeInstalled){ - void this.showCscopeErrorMessage(); - return ""; - } - - if(!fs.existsSync(cscopeOutPath)){ - gDebugLog.error("Cscope.out file doesnt exist"); - } - var command = `${this.cscopePath} -d -C -L${cmdType}${text} `; - let result; - if(textWindow===""){ - result = await exec(command, getEdkCodeFolderPath()); - }else{ - result = await execWindow(command, getEdkCodeFolderPath(), textWindow); - } - return result; - } - - private parseResult(result:string, text:string){ - const cscopeResults = result.toString().split(/\r?\n/); - var searchResult = []; - for (const line of cscopeResults) { - if (line === ''){continue;} - var data = line.replace(/\s+/g,' ').split(" "); - if(data.length >= 3){ - var refLine = Number(data[2])-1; - if(fs.existsSync(data[0]) && (typeof refLine === 'number')){ - searchResult.push(new FuncInfo(data[1], refLine, normalizePath(data[0]), data.slice(3).join(" "), text)); - } - } - } - - return searchResult; - } -} - - -export class CscopeAgent { - - - taskUpdateId: NodeJS.Timeout | undefined; - updateFrequency:number = 6000; - - public constructor() { - let subscriptions: vscode.Disposable[] = []; - - //Trigger cscope updates on saved documents - vscode.workspace.onDidSaveTextDocument(this._updateCscopeDb, this, subscriptions); - } - - async writeCscopeFile(fileList:string[]){ - if(!gConfigAgent.getUseCscope()){ return; } - if(fileList.length === 0){ - return; - } - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - let cscopeFiles = fileList.map((x)=>{return x.replaceAll("/",path.sep);}).join("\n"); - fs.writeFileSync(cscopeFilesPath,cscopeFiles); - await gCscope.reload(); - } - - - removeFiles() { - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - fs.rmSync(cscopeFilesPath, {force:true}); - - let cscopeOutPath = getEdkCodeFolderFilePath("cscope.out"); - fs.rmSync(cscopeOutPath, {force:true}); - - } - - - - - readCscopeFile():string[]{ - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - let lines = readLines(cscopeFilesPath); - if(lines.length===1 && lines[0]===''){return [];} - return lines; - } - - private async _updateCscopeDb(savedFile: vscode.TextDocument) { - /** - * Updates Cscope database based on cscope.files elements - */ - if(!gConfigAgent.getUseCscope()){ return; } - const debouncer = Debouncer.getInstance(); - debouncer.debounce("updateCscopeDb", async () => { - let cscopeFilesPath = getEdkCodeFolderFilePath("cscope.files"); - if(fs.existsSync(cscopeFilesPath)){ - - let isFileUsed = await gEdkWorkspaces.isFileInUse(savedFile.uri); - if(isFileUsed){ - await gCscope.reload(false); - } - } - }, this.updateFrequency); - } -} - diff --git a/src/debouncer.ts b/src/debouncer.ts deleted file mode 100644 index 9dc5dc7..0000000 --- a/src/debouncer.ts +++ /dev/null @@ -1,29 +0,0 @@ -export class Debouncer { - private static instance: Debouncer; - private taskMap: Map; - - private constructor() { - this.taskMap = new Map(); - } - - public static getInstance(): Debouncer { - if (!Debouncer.instance) { - Debouncer.instance = new Debouncer(); - } - return Debouncer.instance; - } - - public debounce(key: string, callback: () => void, delay: number): void { - if (this.taskMap.has(key)) { - clearTimeout(this.taskMap.get(key)); - } - - const taskId = setTimeout(() => { - callback(); - this.taskMap.delete(key); - }, delay); - - this.taskMap.set(key, taskId); - } -} - diff --git a/src/debugLog.ts b/src/debugLog.ts deleted file mode 100644 index fda777b..0000000 --- a/src/debugLog.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as vscode from 'vscode'; -import { gConfigAgent } from './extension'; - -export enum LogLevel { - none = 0, - error, - warning, - info, - verbose, - debug - } - -export class DebugLog { - outConsole: vscode.LogOutputChannel; - - public constructor() { - - this.outConsole = vscode.window.createOutputChannel("EDK2Code", {log:true}); - } - - public show(){ - this.outConsole.show(); - } - - public clear(){ - this.outConsole.clear(); - } - - public error(text:string){ - this.outConsole.error("[EDK2Code] " + text); - let callStack = (new Error()).stack || ''; - this.outConsole.error(`[Stack]\n${callStack}`); - } - - public info(text:string){ - this.outConsole.info("[EDK2Code] " + text); - } - - public trace(text:string){ - this.outConsole.trace("[EDK2Code] " + text); - } - - public warning(text:string){ - this.outConsole.warn("[EDK2Code] " + text); - } - - public debug(text:string){ - this.outConsole.trace("[EDK2Code] " + text); - } - - - - -} \ No newline at end of file diff --git a/src/diagnostics.ts b/src/diagnostics.ts deleted file mode 100644 index ce1626d..0000000 --- a/src/diagnostics.ts +++ /dev/null @@ -1,211 +0,0 @@ -import * as vscode from 'vscode'; -import { gConfigAgent } from './extension'; - - -export enum EdkDiagnosticCodes{ -sectionEmpty = 1000, -mixedSectionTypes, -unknownSectionType, -syntaxSectionType, -syntaxStatement, -statementNoKey, -duplicateStatement, -publicAndPrivate, -undefinedTokenSpaceGuid, -includePathNotFound, -includeFileMultiplePaths, -nestedPackages, -duplicateDeclaration, -duplicateIncludePath, -duplicateGuid, -undefinedLibraryClass, -relativePath, -syntaxPath, -duplicateIncludeFile, -missingPath, -conditionalMissform, -unusedSymbol, -emptyFile, -circularDependency, -inactiveCode, -edk2CodeUnsuported, -errorMessage, - undefinedVariable, - duplicateDefine -} - -export const edkErrorDescriptions: Map = new Map([ - [EdkDiagnosticCodes.sectionEmpty, "Section is empty"], - [EdkDiagnosticCodes.mixedSectionTypes, "Mixed section types are not allowed"], - [EdkDiagnosticCodes.unknownSectionType, "Unknown section type"], - [EdkDiagnosticCodes.syntaxSectionType, "Syntax error in section type"], - [EdkDiagnosticCodes.syntaxStatement, "Syntax error in statement"], - [EdkDiagnosticCodes.statementNoKey, "Statement has no key"], - [EdkDiagnosticCodes.duplicateStatement, "Duplicate statement"], - [EdkDiagnosticCodes.publicAndPrivate, "Public and private modifiers are mutually exclusive"], - [EdkDiagnosticCodes.undefinedTokenSpaceGuid, "Undefined token space GUID"], - [EdkDiagnosticCodes.includePathNotFound, "Include path not found"], - [EdkDiagnosticCodes.includeFileMultiplePaths, "Include file found in multiple paths"], - [EdkDiagnosticCodes.nestedPackages, "Nested packages are not allowed"], - [EdkDiagnosticCodes.duplicateDeclaration, "Duplicate declaration"], - [EdkDiagnosticCodes.duplicateIncludePath, "Duplicate include path"], - [EdkDiagnosticCodes.duplicateGuid, "Duplicate GUID"], - [EdkDiagnosticCodes.undefinedLibraryClass, "Undefined library class"], - [EdkDiagnosticCodes.relativePath, "Relative path not allowed"], - [EdkDiagnosticCodes.syntaxPath, "Syntax error in path"], - [EdkDiagnosticCodes.duplicateIncludeFile, "Duplicate include file"], - [EdkDiagnosticCodes.missingPath, "Missing path"], - [EdkDiagnosticCodes.conditionalMissform, "Conditional block missform"], - [EdkDiagnosticCodes.unusedSymbol, "Unused symbol"], - [EdkDiagnosticCodes.emptyFile, "Empty file"], - [EdkDiagnosticCodes.circularDependency, "Circular dependency"], - [EdkDiagnosticCodes.inactiveCode, "Inactive code"], - [EdkDiagnosticCodes.edk2CodeUnsuported, "Edk2Code unsupported"], - [EdkDiagnosticCodes.errorMessage, "Error message"], - [EdkDiagnosticCodes.undefinedVariable, "Undefined variable"], - [EdkDiagnosticCodes.duplicateDefine, "Duplicate DEFINE overrides previous value"], - ]); - -export class DiagnosticManager { - private static instance: DiagnosticManager; - private static diagnosticsCollection: vscode.DiagnosticCollection; - private static diagnostics:Map = new Map(); - - private constructor() { - // Prevent reinitialization of the diagnosticsCollection - if (!DiagnosticManager.diagnosticsCollection) { - DiagnosticManager.diagnosticsCollection = vscode.languages.createDiagnosticCollection('edk2Problems'); - } - } - - public static getInstance(): DiagnosticManager { - if (!DiagnosticManager.instance) { - DiagnosticManager.instance = new DiagnosticManager(); - } - return DiagnosticManager.instance; - } - - public static warning(documentUri: vscode.Uri, line: number | vscode.Range, edkDiagCode: EdkDiagnosticCodes, detail:string, tags: vscode.DiagnosticTag[] = [], - relatedInformation?: vscode.DiagnosticRelatedInformation[]|undefined) { - if(!edkErrorDescriptions.has(edkDiagCode)){ - throw new Error(`Unknown EDK diagnostic code: ${edkDiagCode}`); - } - return DiagnosticManager.reportProblem(documentUri, line, edkErrorDescriptions.get(edkDiagCode)!+": "+detail, vscode.DiagnosticSeverity.Warning,"EDK2Code",edkDiagCode, tags, relatedInformation); - } - - public static info(documentUri: vscode.Uri, line: number | vscode.Range, edkDiagCode: EdkDiagnosticCodes, detail:string, tags: vscode.DiagnosticTag[] = [], - relatedInformation?: vscode.DiagnosticRelatedInformation[]|undefined) { - if(!edkErrorDescriptions.has(edkDiagCode)){ - throw new Error(`Unknown EDK diagnostic code: ${edkDiagCode}`); - } - return DiagnosticManager.reportProblem(documentUri, line, edkErrorDescriptions.get(edkDiagCode)!+": "+detail, vscode.DiagnosticSeverity.Information,"EDK2Code",edkDiagCode, tags, relatedInformation); - } - - public static hint(documentUri: vscode.Uri, line: number | vscode.Range, edkDiagCode: EdkDiagnosticCodes, detail:string, tags: vscode.DiagnosticTag[] = [], - relatedInformation?: vscode.DiagnosticRelatedInformation[]|undefined) { - if(!edkErrorDescriptions.has(edkDiagCode)){ - throw new Error(`Unknown EDK diagnostic code: ${edkDiagCode}`); - } - return DiagnosticManager.reportProblem(documentUri, line, edkErrorDescriptions.get(edkDiagCode)!+": "+detail, vscode.DiagnosticSeverity.Hint,"EDK2Code",edkDiagCode, tags, relatedInformation); - } - - public static error(documentUri: vscode.Uri, line: number | vscode.Range, edkDiagCode: EdkDiagnosticCodes, detail:string, tags: vscode.DiagnosticTag[] = [], - relatedInformation?: vscode.DiagnosticRelatedInformation[]|undefined) { - if(!edkErrorDescriptions.has(edkDiagCode)){ - throw new Error(`Unknown EDK diagnostic code: ${edkDiagCode}`); - } - return DiagnosticManager.reportProblem(documentUri, line, edkErrorDescriptions.get(edkDiagCode)!+": "+detail, vscode.DiagnosticSeverity.Error,"EDK2Code",edkDiagCode, tags, relatedInformation); - } - - private static addDiagnostic(documentUri: vscode.Uri, diagnostic: vscode.Diagnostic) { - if (!DiagnosticManager.diagnostics.has(documentUri.fsPath)) { - DiagnosticManager.diagnostics.set(documentUri.fsPath, []); - } - DiagnosticManager.diagnostics.get(documentUri.fsPath)!.push(diagnostic); - } - - private static getDiagnostic(documentUri: vscode.Uri): vscode.Diagnostic[] { - return DiagnosticManager.diagnostics.get(documentUri.fsPath) || []; - } - - /** - * Find a diagnostic matching one of the given codes at a specific line for a URI. - * Returns the first matching diagnostic, or undefined. - */ - public static findDiagnosticAt(documentUri: vscode.Uri, line: number, codes: EdkDiagnosticCodes[]): vscode.Diagnostic | undefined { - const diags = DiagnosticManager.diagnostics.get(documentUri.fsPath); - if (!diags) { return undefined; } - return diags.find(d => d.range.start.line === line && codes.includes(d.code as number)); - } - - private static clearDiagnostic(documentUri: vscode.Uri) { - DiagnosticManager.diagnostics.delete(documentUri.fsPath); - } - - private static clearAllDiagnostics() { - DiagnosticManager.diagnostics.clear(); - } - - public static reportProblem(documentUri: vscode.Uri, - line: number|vscode.Range, - message: string, - severity: vscode.DiagnosticSeverity, - source?: string, - code?: string | number, - tags: vscode.DiagnosticTag[]= [], - relatedInformation?: vscode.DiagnosticRelatedInformation[]|undefined) - { - - - - if(gConfigAgent.isDiagnostics() === false){ - this.clearAllProblems(); - return undefined; - } - - // Create a range that covers the entire line - let range:vscode.Range; - if (line instanceof vscode.Range) { - range = line; - }else{ - range = new vscode.Range(line as number, 0, line as number, Number.MAX_VALUE); - } - - // Check if the diagnostic already exists - const existingDiagnostics = DiagnosticManager.getDiagnostic(documentUri); - const isDuplicate = existingDiagnostics.some(diagnostic => - diagnostic.range.isEqual(range) && - diagnostic.message === message && - diagnostic.severity === severity - ); - - if (isDuplicate) { - return undefined; // Skip adding duplicate diagnostic - } - - - const diagnostic = new vscode.Diagnostic(range, message, severity); - if (source) { - diagnostic.source = source; - } - if (code) { - diagnostic.code = code; - } - diagnostic.tags = tags; - diagnostic.relatedInformation = relatedInformation; - - DiagnosticManager.addDiagnostic(documentUri, diagnostic); - DiagnosticManager.diagnosticsCollection.set(documentUri, DiagnosticManager.getDiagnostic(documentUri)); - return diagnostic; - } - - public static clearAllProblems() { - DiagnosticManager.clearAllDiagnostics(); - DiagnosticManager.diagnosticsCollection.clear(); - } - - public static clearProblems(documentUri: vscode.Uri) { - DiagnosticManager.clearDiagnostic(documentUri); - DiagnosticManager.diagnosticsCollection.delete(documentUri); - } -} diff --git a/src/driverInfoTree/DriverInfoTreeProvider.ts b/src/driverInfoTree/DriverInfoTreeProvider.ts deleted file mode 100644 index b7d00a5..0000000 --- a/src/driverInfoTree/DriverInfoTreeProvider.ts +++ /dev/null @@ -1,424 +0,0 @@ -import * as vscode from 'vscode'; -import * as path from 'path'; -import { gEdkWorkspaces, gPathFind, gCompileCommands } from '../extension'; -import { getParser } from '../edkParser/parserFactory'; -import { EdkSymbol } from '../symbols/edkSymbols'; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import { DocumentParser } from '../edkParser/languageParser'; -import { rgSearch } from '../rg'; - -// ─── Tree item types ────────────────────────────────────────────────────────── - -export class DriverInfoCategoryItem extends vscode.TreeItem { - children: DriverInfoLeafItem[] = []; - constructor(label: string, icon: string) { - super(label, vscode.TreeItemCollapsibleState.Expanded); - this.iconPath = new vscode.ThemeIcon(icon); - this.contextValue = 'driverInfoCategory'; - } -} - -export class DriverInfoLeafItem extends vscode.TreeItem { - constructor( - label: string, - description: string, - icon: vscode.ThemeIcon, - command?: vscode.Command, - fileUri?: vscode.Uri - ) { - super(label, vscode.TreeItemCollapsibleState.None); - this.description = description; - this.iconPath = icon; - if (fileUri) { - this.resourceUri = fileUri; - this.iconPath = vscode.ThemeIcon.File; - } - if (command) { - this.command = command; - } - } -} - -type DriverInfoNode = DriverInfoCategoryItem | DriverInfoLeafItem; - -// ─── Provider ───────────────────────────────────────────────────────────────── - -export class DriverInfoTreeProvider implements vscode.TreeDataProvider { - - private _onDidChangeTreeData = new vscode.EventEmitter(); - readonly onDidChangeTreeData = this._onDidChangeTreeData.event; - - private categories: DriverInfoCategoryItem[] = []; - private _infUri: vscode.Uri | undefined; - private get infUri() { return this._infUri; } - private set infUri(v: vscode.Uri | undefined) { this._infUri = v; } - get currentInfUri(): vscode.Uri | undefined { return this._infUri; } - private parser: DocumentParser | undefined; - private _treeView: vscode.TreeView | undefined; - - /** Set the tree view reference so the provider can update its title. */ - setTreeView(treeView: vscode.TreeView) { - this._treeView = treeView; - } - private disposables: vscode.Disposable[] = []; - private _suppressNextUpdate = false; - private _lastEditorFsPath: string | undefined; - private _lastSuppressTime = 0; - - /** Call before programmatically opening a file to prevent the driver info from refreshing. - * Returns true if suppression was set (single click), false if double-click was detected. */ - suppressNextUpdate(): boolean { - const now = Date.now(); - if (now - this._lastSuppressTime < 500) { - // Double-click detected: cancel suppression so driver info updates - this._suppressNextUpdate = false; - this._lastSuppressTime = 0; - return false; - } else { - this._suppressNextUpdate = true; - this._lastSuppressTime = now; - return true; - } - } - - constructor() { - this.disposables.push( - vscode.window.onDidChangeActiveTextEditor(async (editor) => { - if (editor) { - if (!this._suppressNextUpdate) { - this._lastEditorFsPath = editor.document.uri.fsPath; - } - await this.onEditorChanged(editor); - } - }), - vscode.window.onDidChangeTextEditorSelection(async (e) => { - // Fires when the user clicks into an already-active editor (focus-back). - // Only process if the document differs from what is currently displayed. - if (e.textEditor.document.uri.fsPath !== this._lastEditorFsPath) { - this._lastEditorFsPath = e.textEditor.document.uri.fsPath; - await this.onEditorChanged(e.textEditor); - } - }) - ); - } - - dispose() { - for (const d of this.disposables) { d.dispose(); } - } - - getTreeItem(element: DriverInfoNode): vscode.TreeItem { - return element; - } - - getChildren(element?: DriverInfoNode): DriverInfoNode[] { - if (!element) { - return this.categories; - } - if (element instanceof DriverInfoCategoryItem) { - return element.children; - } - return []; - } - - // ─── Editor change handler ──────────────────────────────────────────────── - - async onEditorChanged(editor: vscode.TextEditor) { - if (this._suppressNextUpdate) { - this._suppressNextUpdate = false; - return; - } - - const document = editor.document; - const langId = document.languageId; - - // Only process EDK-relevant files - if (!['c', 'cpp', 'edk2_dsc', 'edk2_inf', 'edk2_dec', 'asl', 'edk2_vfr', 'edk2_fdf', 'edk2_uni'].includes(langId)) { - this.clear(); - return; - } - - // Check if file is in use - if (gEdkWorkspaces.isConfigured()) { - const isUsed = await gEdkWorkspaces.isFileInUse(document.uri); - if (isUsed !== true) { - this.clear(); - return; - } - } - - // Find the INF file - const infUri = await this.findInfForFile(document.uri); - if (!infUri) { - this.clear(); - return; - } - - // If same INF, no need to rebuild - if (this.infUri && this.infUri.fsPath === infUri.fsPath) { - return; - } - - this.infUri = infUri; - await this.buildTree(); - } - - // ─── Locate INF file ────────────────────────────────────────────────────── - - private async findInfForFile(fileUri: vscode.Uri): Promise { - // If the file itself is an INF - if (fileUri.fsPath.match(/\.inf$/i)) { - return fileUri; - } - - const wps = await gEdkWorkspaces.getWorkspace(fileUri); - if (wps.length) { - for (const wp of wps) { - const locations = await wp.getInfReference(fileUri); - if (locations.length) { - return locations[0].uri; - } - } - } else { - // Fallback: search for INF file referencing this source - const fileName = path.basename(fileUri.fsPath); - const folderPath = path.dirname(fileUri.fsPath); - const tempLocations = await rgSearch(`\\b${fileName}\\b`, ['*.inf'], [], true); - for (const l of tempLocations) { - if (!path.relative(path.dirname(l.uri.fsPath), folderPath).includes('..')) { - return l.uri; - } - } - } - return undefined; - } - - // ─── Build tree from INF parser ─────────────────────────────────────────── - - private async buildTree() { - this.categories = []; - - if (!this.infUri) { - this.refresh(); - return; - } - - const parser = await getParser(this.infUri); - if (!parser) { - this.refresh(); - return; - } - this.parser = parser; - - await vscode.commands.executeCommand('setContext', 'edk2code.driverInfoAvailable', true); - - // Set view title to BASE_NAME - const defines = parser.getSymbolsType(Edk2SymbolType.infDefine); - let baseName = ''; - for (const def of defines) { - const key = await def.getKey(); - if (key.toLowerCase() === 'base_name') { - baseName = await def.getValue(); - break; - } - } - if (this._treeView) { - this._treeView.title = baseName || path.basename(this.infUri.fsPath); - } - - // Defines - if (defines.length) { - const cat = new DriverInfoCategoryItem('Defines', 'symbol-constant'); - for (const def of defines) { - const key = await def.getKey(); - const value = await def.getValue(); - const item = new DriverInfoLeafItem( - key, - value, - new vscode.ThemeIcon('symbol-property'), - { - command: 'edk2code.driverInfoOpenFile', - title: 'Open', - arguments: [def.location.uri, { selection: def.location.range }] - } - ); - cat.children.push(item); - } - this.categories.push(cat); - } - - // Sources - const sources = parser.getSymbolsType(Edk2SymbolType.infSource); - if (sources.length) { - const cat = new DriverInfoCategoryItem('Sources', 'files'); - gCompileCommands.load(); - for (const src of sources) { - const filePath = src.textLine.replace(/\s*\|.*/, ''); - const relPath = path.dirname(this.infUri.fsPath); - const locations = await gPathFind.findPath(filePath, relPath); - const resolvedUri = locations.length ? locations[0].uri : vscode.Uri.file(path.join(relPath, filePath)); - const hasCompileCommand = gCompileCommands.getCompileCommandForFile(resolvedUri.fsPath) !== undefined; - const item = new DriverInfoLeafItem( - filePath, - '', - vscode.ThemeIcon.File, - locations.length ? { - command: 'edk2code.driverInfoOpenFile', - title: 'Open file', - arguments: [locations[0].uri] - } : undefined, - resolvedUri - ); - if (hasCompileCommand) { - item.contextValue = 'driverInfoCompilableSource'; - } - cat.children.push(item); - } - this.categories.push(cat); - } - - // Libraries - const libraries = parser.getSymbolsType(Edk2SymbolType.infLibrary); - if (libraries.length) { - const cat = new DriverInfoCategoryItem('Libraries', 'library'); - for (const lib of libraries) { - const libName = lib.textLine.replace(/\s*\|.*/, ''); - const item = new DriverInfoLeafItem( - libName, - '', - new vscode.ThemeIcon('symbol-module'), - { - command: 'edk2code.driverInfoGoToDefinition', - title: 'Go to definition', - arguments: [lib] - } - ); - cat.children.push(item); - } - this.categories.push(cat); - } - - // Packages - const packages = parser.getSymbolsType(Edk2SymbolType.infPackage); - if (packages.length) { - const cat = new DriverInfoCategoryItem('Packages', 'package'); - for (const pkg of packages) { - const pkgPath = pkg.textLine.replace(/\s*\|.*/, ''); - const item = new DriverInfoLeafItem( - pkgPath, - '', - new vscode.ThemeIcon('symbol-package'), - { - command: 'edk2code.driverInfoGoToDefinition', - title: 'Go to definition', - arguments: [pkg] - } - ); - cat.children.push(item); - } - this.categories.push(cat); - } - - // Protocols - const protocols = parser.getSymbolsType(Edk2SymbolType.infProtocol); - if (protocols.length) { - const cat = new DriverInfoCategoryItem('Protocols', 'plug'); - for (const proto of protocols) { - const protoName = proto.textLine.replace(/\s*\|.*/, ''); - const item = new DriverInfoLeafItem( - protoName, - '', - new vscode.ThemeIcon('symbol-interface'), - { - command: 'edk2code.driverInfoGoToDefinition', - title: 'Go to definition', - arguments: [proto] - } - ); - cat.children.push(item); - } - this.categories.push(cat); - } - - // PPIs - const ppis = parser.getSymbolsType(Edk2SymbolType.infPpi); - if (ppis.length) { - const cat = new DriverInfoCategoryItem('PPIs', 'plug'); - for (const ppi of ppis) { - const ppiName = ppi.textLine.replace(/\s*\|.*/, ''); - const item = new DriverInfoLeafItem( - ppiName, - '', - new vscode.ThemeIcon('symbol-event'), - { - command: 'edk2code.driverInfoGoToDefinition', - title: 'Go to definition', - arguments: [ppi] - } - ); - cat.children.push(item); - } - this.categories.push(cat); - } - - // GUIDs - const guids = parser.getSymbolsType(Edk2SymbolType.infGuid); - if (guids.length) { - const cat = new DriverInfoCategoryItem('GUIDs', 'key'); - for (const guid of guids) { - const guidName = guid.textLine.replace(/\s*\|.*/, ''); - const item = new DriverInfoLeafItem( - guidName, - '', - new vscode.ThemeIcon('symbol-number'), - { - command: 'edk2code.driverInfoGoToDefinition', - title: 'Go to definition', - arguments: [guid] - } - ); - cat.children.push(item); - } - this.categories.push(cat); - } - - // PCDs - const pcds = parser.getSymbolsType(Edk2SymbolType.infPcd); - if (pcds.length) { - const cat = new DriverInfoCategoryItem('PCDs', 'settings'); - for (const pcd of pcds) { - const pcdName = pcd.textLine.replace(/\s*\|.*/, ''); - const item = new DriverInfoLeafItem( - pcdName, - '', - new vscode.ThemeIcon('symbol-string'), - { - command: 'edk2code.driverInfoGoToDefinition', - title: 'Go to definition', - arguments: [pcd] - } - ); - cat.children.push(item); - } - this.categories.push(cat); - } - - this.refresh(); - } - - // ─── Helpers ────────────────────────────────────────────────────────────── - - private clear() { - this.categories = []; - this.infUri = undefined; - this.parser = undefined; - if (this._treeView) { - this._treeView.title = 'Module Info'; - } - void vscode.commands.executeCommand('setContext', 'edk2code.driverInfoAvailable', false); - this.refresh(); - } - - private refresh() { - this._onDidChangeTreeData.fire(); - } -} diff --git a/src/edk2CodeFolder.ts b/src/edk2CodeFolder.ts deleted file mode 100644 index d0914ad..0000000 --- a/src/edk2CodeFolder.ts +++ /dev/null @@ -1,59 +0,0 @@ -import path = require("path"); -import * as cp from 'child_process'; -import * as fs from 'fs'; -import * as vscode from 'vscode'; -import { gDebugLog, gWorkspacePath } from "./extension"; - -export function existsEdkCodeFolderFile(filename: string) { - return fs.existsSync(path.join(gWorkspacePath, ".edkCode", filename)); -} - -export function createEdkCodeFolder() { - if (!fs.existsSync(path.join(gWorkspacePath, ".edkCode"))) { - fs.mkdirSync(path.join(gWorkspacePath, ".edkCode")); - } -} - -export function writeEdkCodeFolderFile(filename: string, text: string) { - createEdkCodeFolder(); - if(!existsEdkCodeFolderFile(filename)){ - - } - fs.writeFileSync(path.join(gWorkspacePath, ".edkCode", filename), text); -} - -/* - * Returns the path of a filename in .edkCode folder. -*/ -export function getEdkCodeFolderFilePath(filename: string) { - //Returns the path to filename inside EdkCode folder - return path.join(gWorkspacePath, ".edkCode", filename); -} - -export function getEdkCodeFolderPath() { - return path.join(gWorkspacePath, ".edkCode"); -} - -export function readEdkCodeFolderFile(filename: string) { - let p = path.join(gWorkspacePath, ".edkCode", filename); - if (!fs.existsSync(p)) { - return undefined; - } - return fs.readFileSync(p).toString(); -} - - -export function deleteEdkCodeFolderFile(filename: string) { - let p = path.join(gWorkspacePath, ".edkCode", filename); - fs.rmSync(p, { force: true }); -} - -export function deleteEdkCodeFolder() { - let p = path.join(gWorkspacePath, ".edkCode"); - try { - fs.rmSync(p, { recursive: true, force: true }); - } catch (error: any) { - gDebugLog.error(`deleteEdkCodeFolder: ${error}`); - } - createEdkCodeFolder(); -} diff --git a/src/edkParser/README.md b/src/edkParser/README.md deleted file mode 100644 index 86e33a8..0000000 --- a/src/edkParser/README.md +++ /dev/null @@ -1,297 +0,0 @@ -# EDK II Language Parser - -This folder implements a recursive-descent, line-oriented parser that transforms EDK II source files (`.dsc`, `.inf`, `.dec`, `.fdf`, `.vfr`, `.asl`) into a tree of `EdkSymbol` objects used for navigation, outline views, and diagnostics throughout the extension. - -## Architecture Overview - -``` - ParserFactory - | - selects by languageId - | - ┌─────────┬──────┴──────┬──────────┐ - DscParser InfParser DecParser FdfParser ... - │ - (extends DocumentParser) - │ - blockParsers: BlockParser[] ← top-level parsers - │ - └─ each BlockParser has - tag / start / end ← regex rules - context: BlockParser[] ← nested parsers -``` - -### Key classes - -| Class | File | Role | -|---|---|---| -| `BlockParser` | `languageParser.ts` | Abstract block parser — matches, opens, and closes blocks using regex rules | -| `DocumentParser` | `languageParser.ts` | Base class for all language parsers — drives the line-by-line loop and manages the symbol tree/stack | -| `ParserFactory` | `parserFactory.ts` | Instantiates the correct `DocumentParser` subclass by VS Code `languageId` | -| `DscParser`, `InfParser`, etc. | `dscParser.ts`, `infParser.ts`, etc. | Concrete parsers that define `blockParsers`, comment syntax, and language-specific state | - ---- - -## Parsing Lifecycle - -### 1. Entry point — `parseFile()` - -``` -DocumentParser.parseFile() - ┌─────────────────────────────────────┐ - │ for each line in the document: │ - │ skip comment lines │ - │ call parseLine() │ - │ increment lineIndex │ - └─────────────────────────────────────┘ -``` - -`parseFile()` iterates from line 1 to the end of the document. For every non-comment line it calls `parseLine()`. - -### 2. Top-level dispatch — `parseLine()` - -```typescript -async parseLine() { - for (parseIndex = 0 .. blockParsers.length) { - decrementLineIndex(); // rewind so block.parse() can re-read - result = blockParsers[parseIndex].parse(this); - if (result) { - // If the block consumed multiple lines (has start/end), reset - // parseIndex to -1 so parsing continues from the first parser - // on the new current line. - // If the block is root-only or single-line, just continue - // trying the next parser on the same line. - } - } -} -``` - -Each `BlockParser` in `blockParsers` is tried in order. When a parser matches and it is a multi-line block (has `start`/`end`), `parseIndex` resets to `-1` so the next line is evaluated again from the first parser. Single-line or root-only parsers let the loop continue without resetting. - ---- - -## BlockParser — Start, Content, and End - -The core parsing logic lives in `BlockParser.parse()`. A block parser is configured by four regex properties and a list of child parsers: - -| Property | Required | Purpose | -|---|---|---| -| `tag` | **yes** | Regex the current line must match for this block to activate | -| `excludeTag` | no | If the line matches this regex, the block is skipped even if `tag` matches | -| `start` | no | Regex marking the beginning of the block's body (e.g. `{`) | -| `end` | no | Regex marking the end of the block (e.g. `}` or `[`) | -| `context` | no | Child `BlockParser[]` that will be tried on every line inside the block body | - -### Three block shapes - -The combination of `start` and `end` determines how a block behaves: - -#### Single-line block (`start = undefined`, `end = undefined`) - -``` - tag matches → create symbol → pop immediately → return true -``` - -The block matches exactly one line. The symbol is created and immediately finalized. Examples: `BlockDefinition`, `BlocklibraryDef`, `BlockPcd`, `BlockBuildOption`. - -#### Section block (`start = undefined`, `end = /regex/`) - -``` - tag matches → create symbol → push onto stack - for each subsequent line: - try context[] child parsers - if line matches end → pop symbol → return true - EOF → pop symbol → return true -``` - -The block begins at the `tag` line and continues until a line matches `end`. Every line inside the block is tested against `context[]` child parsers. Examples: `BlockComponentsSection` (ends at `^\[`), `BlockComponentSubLibraryClasses` (ends at `^<` or `^\}`). - -#### Delimited block (`start = /regex/`, `end = /regex/`) - -``` - tag matches → create symbol → push onto stack - scan forward until a line matches start (e.g. "{") - (if end is hit first, pop and return early) - then for each subsequent line: - try context[] child parsers - if line matches end → pop symbol → return true - EOF → pop symbol → return true -``` - -After the tag line matches, the parser scans forward looking for the `start` delimiter before entering the content loop. This handles constructs where the opening brace may appear on the same line as the tag or on a subsequent line. Example: `BlockComponentInf` (tag matches `*.inf`, start matches `{`, end matches `}` or `[`). - -### Flowchart - -``` -parse(docParser) - │ - ├─ read line, check tag/excludeTag - │ └─ no match → return false - │ - ├─ check isRoot constraint - │ - ├─ create EdkSymbol via SymbolFactory - │ └─ addSymbol() + pushSymbolStack() - │ - ├─ if start is defined: - │ │ scan lines until start matches - │ │ (if end matches first → popSymbolStack, return true) - │ │ - │ └─ fall through to content loop ↓ - │ - ├─ else if end is undefined: - │ └─ single-line: popSymbolStack → return true - │ - ├─ else: fall through to content loop ↓ - │ - ├─ CONTENT LOOP: while hasPendingLines() - │ │ - │ ├─ read next line (skip empty) - │ │ - │ ├─ for each child in context[]: - │ │ │ decrement lineIndex (rewind) - │ │ │ child.parse(docParser) ← recursive - │ │ │ if matched and exclusive → break - │ │ │ - │ │ - │ └─ if line matches end → popSymbolStack → return true - │ - └─ EOF reached → popSymbolStack → return true -``` - ---- - -## How Symbols Are Added - -### Symbol creation - -When a `BlockParser`'s `tag` matches, a symbol is created through this sequence: - -1. **Range** — An initial range is created from the matched line's start to the end of the document (a placeholder that gets narrowed later). -2. **SymbolFactory** — `symbolFactory.produceSymbol(type, textLine, location, parser)` instantiates the specific `EdkSymbol` subclass based on the `Edk2SymbolType` enum. -3. **addSymbol()** — The symbol is placed into the tree: - - If `symbolStack` is empty → pushed to `symbolsTree` (root level). - - Otherwise → added as a `child` of the current top-of-stack symbol, and `parent` is set. - - In all cases, also appended to the flat `symbolsList`. -4. **pushSymbolStack()** — The symbol is pushed onto the stack to become the current parent for any nested symbols. - -### Symbol finalization - -When the block ends (either by matching `end`, reaching EOF, or being a single-line block), `popSymbolStack()` is called: - -- The symbol is popped from the stack. -- Its **range is narrowed**: the end position is adjusted from the initial "rest of document" placeholder to the actual last line the block covered. - - If the symbol has children → end is set to `lineIndex - 2` (the line before the end delimiter). - - If no children → end is set to `lineIndex - 1` (the tag line itself for single-line blocks). - -### Tree structure - -After parsing, `DocumentParser` holds two views of the symbols: - -| Collection | Type | Description | -|---|---|---| -| `symbolsTree` | `EdkSymbol[]` | Hierarchical tree — only root-level symbols; children are nested via `symbol.children` | -| `symbolsList` | `EdkSymbol[]` | Flat list — every symbol in document order, for fast iteration and filtering | - -The tree structure corresponds directly to block nesting. For example, parsing a DSC `[Components]` section produces: - -``` -EdkSymbolDscSection "Components.X64" - ├─ EdkSymbolDscModuleDefinition "Module.inf" - │ ├─ EdkSymbolDscComponentSubSection "" - │ │ └─ EdkSymbolDscLibraryDefinition "Lib|Path.inf" - │ ├─ EdkSymbolDscComponentSubSection "" - │ │ └─ EdkSymbolDscPcdDefinition "gPkg.PcdName|value" - │ └─ EdkSymbolDscComponentSubSection "" - │ └─ EdkSymbolDscBuildOption "MSFT:*_*_*_CC_FLAGS = /D FLAG" - └─ EdkSymbolDscModuleDefinition "Other.inf" -``` - ---- - -## Root-only parsers (`isRoot = true`) - -Some parsers are registered twice in `blockParsers`: - -```typescript -blockParsers: BlockParser[] = [ - new BlockComponentsSection(), // normal: matches inside any context - // ... - new BlockComponentInf(true), // isRoot: only matches at the document root -]; -``` - -When `isRoot` is `true`, the parser only activates when `symbolStack` is empty (i.e. no parent block is open). This allows a block to act as a "catch-all" for lines that appear outside any section, ensuring they still get a symbol without interfering with the normal section hierarchy. - ---- - -## `startContext` / `endContext` — alternate end delimiter - -Some EDK II constructs use a delimiter that appears *on the same line as the tag* to enter a special sub-block, and that sub-block requires a different `end` pattern than the surrounding block. `startContext` and `endContext` handle this case without needing a separate `BlockParser`. - -| Property | Type | Purpose | -|---|---|---| -| `startContext` | `RegExp \| undefined` | If this pattern matches the tag line (or any line scanned while looking for `start`), the block switches to `endContext` as its terminator | -| `endContext` | `RegExp \| undefined` | Alternative `end` regex used only when `startContext` was matched | - -### How it works - -1. After the `tag` matches and the symbol is created, the parser checks whether the tag line also matches `startContext`. If so, `inContext = true`. -2. While scanning forward looking for `start`, each scanned line is also tested against `startContext`. -3. Once the content loop begins, `activeEnd` is resolved: - - `inContext && endContext` → `activeEnd = endContext` - - otherwise → `activeEnd = end` -4. Additionally, after a child context parser consumes a line, the **last consumed line** is peeked and tested against `endContext`. This handles the case where the child parser itself consumed the closing delimiter. - -### Example — `BlockComponentInf` - -`BlockComponentInf` matches `*.inf` lines. A component entry can optionally have an opening brace `{` on the same (or next) line, introducing a sub-block with scoped overrides. Without `startContext`/`endContext`, both `{...}` and bare entries would need separate parsers. - -```typescript -class BlockComponentInf extends BlockParser { - tag = /^[\s\.\w\$\(\)_\-\\\/]*\.inf/gi; - start = /.*?{/; // look for the opening brace - end = /(^\})|(^\[)|(\.inf)|(^\!include)/gi; // bare-entry terminators - startContext = /\{/; // brace on the tag/start line → enter context mode - endContext = /^\s*\}/gi; // context mode ends only on closing brace - // ... -} -``` - -When `{` is found, `inContext` becomes `true` and `endContext` (`^\s*\}`) takes over from `end`, so only a closing brace terminates the sub-block. When `{` is absent, `end` applies as usual and the entry is treated as a single-line construct. - ---- - -## `exclusive` flag - -When a child parser in `context[]` matches a line and `exclusive` is `true` (the default), no further child parsers are tried for that line. Setting `exclusive = false` would allow multiple child parsers to process the same line. - ---- - -## Comment handling - -Each `DocumentParser` subclass defines its comment syntax: - -```typescript -commentStart: string = "/*"; // block comment open -commentEnd: string = "*/"; // block comment close -commentLine: string[] = ["#"]; // line comment prefixes -``` - -`removeComment()` strips line comments and tracks block comment state via the `inComment` flag. Lines that are entirely comments are skipped by `parseFile()` before calling `parseLine()`. - ---- - -## File Overview - -| File | Purpose | -|---|---| -| `languageParser.ts` | `BlockParser` + `DocumentParser` base classes | -| `parserFactory.ts` | Factory that instantiates the correct parser by `languageId` | -| `commonParser.ts` | Shared regex constants used across language parsers | -| `dscParser.ts` | DSC file parser (sections, components, library classes, PCDs, build options) | -| `infParser.ts` | INF module file parser | -| `decParser.ts` | DEC package declaration parser | -| `fdfParser.ts` | FDF flash description parser | -| `vfrParser.ts` | VFR visual forms parser | -| `aslParser.ts` | ASL/ACPI source parser | diff --git a/src/edkParser/aslParser.ts b/src/edkParser/aslParser.ts deleted file mode 100644 index 0158440..0000000 --- a/src/edkParser/aslParser.ts +++ /dev/null @@ -1,139 +0,0 @@ - -import { Edk2SymbolType } from "../symbols/symbolsType"; -import { createRange, split } from "../utils"; -import { REGEX_ANY_BUT_SECTION, REGEX_DEFINE } from "./commonParser"; -import { BlockParser, DocumentParser } from "./languageParser"; - - -class BlockDefinitionBlock extends BlockParser { - name = "DefinitionBlock"; - tag = /\bDefinitionBlock\b/gi; - start = /\{/gi; - end = /\}/gi; - type = Edk2SymbolType.aslDefinitionBlock; - visible:boolean = true; - context: BlockParser[] = [ - new BlockExternal(), - new BlockScope(), - new BlockDevice(), - new BlockName(), - new BlockMethod(), - new BlockField(), - new BlockOperationRegion(), - ]; -} - -class BlockExternal extends BlockParser { - name = "External"; - tag = /\bExternal\b/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.aslExternal; - visible:boolean = true; - context: BlockParser[] = [ - - ]; -} - -class BlockScope extends BlockParser { - name = "Scope"; - tag = /\bScope\b/gi; - start = /\{/gi; - end = /\}/gi; - type = Edk2SymbolType.aslScope; - visible:boolean = true; - context: BlockParser[] = [ - new BlockExternal(), - new BlockName(), - new BlockField(), - new BlockOperationRegion(), - new BlockDevice(), - ]; -} - -class BlockDevice extends BlockParser { - name = "Device"; - tag = /\bDevice\b/gi; - start = /\{/gi; - end = /\}/gi; - type = Edk2SymbolType.aslDevice; - visible:boolean = true; - context: BlockParser[] = [ - new BlockExternal(), - new BlockName(), - new BlockField(), - new BlockOperationRegion(), - new BlockMethod(), - ]; -} - -class BlockName extends BlockParser { - name = "Name"; - tag = /\bName\b/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.aslName; - visible:boolean = true; - context: BlockParser[] = [ - - ]; -} - -class BlockMethod extends BlockParser { - name = "Method"; - tag = /\bMethod\b/gi; - start = /\{/gi; - end = /\}/gi; - type = Edk2SymbolType.aslMethod; - visible:boolean = true; - context: BlockParser[] = [ - new BlockExternal(), - new BlockName(), - new BlockField(), - new BlockOperationRegion(), - ]; -} - -class BlockField extends BlockParser { - name = "Field"; - tag = /\bField\b/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.aslField; - visible:boolean = true; - context: BlockParser[] = [ - - ]; -} - - -class BlockOperationRegion extends BlockParser { - name = "OperationRegion"; - tag = /\bOperationRegion\b/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.aslOpRegion; - visible:boolean = true; - context: BlockParser[] = [ - - ]; -} - - -export class AslParser extends DocumentParser { - commentStart: string = "/*"; - commentEnd: string = "*/"; - commentLine: string[] = ["//"]; - - blockParsers: BlockParser[] = [ -new BlockDefinitionBlock(), -new BlockExternal(true), -new BlockScope(), -new BlockDevice(), -new BlockName(true), -new BlockMethod(), -new BlockField(true), -new BlockOperationRegion(true), - -]; -} diff --git a/src/edkParser/commonParser.ts b/src/edkParser/commonParser.ts deleted file mode 100644 index b4cbeb7..0000000 --- a/src/edkParser/commonParser.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const REGEX_DEFINE = /^\s*(?:DEFINE\s+\w+|)\s*=.*/gi; -export const REGEX_INCLUDE = /\s*\!include/gi; -export const REGEX_EQUAL = /\s*\w+\s*=\s*?.*/gi; -export const REGEX_PATH_FILE = /(?<=^.*?\|\s*)[a-zA-Z\/\\0-9\._]+\.([a-z\d])/gi; -export const REGEX_PATH_FOLDER = /^\s*[a-zA-Z\/\\0-9\._]+/gi; - -export const REGEX_LIBRARY_PATH = /(?<=^.*?\|\s*)[a-zA-Z\/\\0-9\._]+\.(.*)/gi; -export const REGEX_MODULE_PATH = /^[a-zA-Z\/\\0-9\._]+\.(inf)/gi; -export const REGEX_DSC_SECTION = /(?<=^\[\s*)[a-z\.,\s\d_]+(?=\])/gi; -export const REGEX_ANY_BUT_SECTION = /^(?!.*?\[).*/gi; -export const REGEX_PCD_LINE = /(?:^\w[\w\d\[\]]+\.)+[\w\d\[\]]+/gi; - -export const REGEX_VAR_USAGE = /\$\(\s*.*?\s*\)/gi; - -export const REGEX_GUID = /^\s*[a-z\d]+\s*=\s*\{\s*0x[a-f\d]{8}\s*,\s*0x[a-f\d]{4}\s*,\s*0x[a-f\d]{4}\s*,\s*\{\s*0x[a-f\d]{2}\s*,\s*0x[a-f\d]{2}\s*,\s*0x[a-f\d]{2}\s*,\s*0x[a-f\d]{2}\s*,\s*0x[a-f\d]{2}\s*,\s*0x[a-f\d]{2}\s*,\s*0x[a-f\d]{2}\s*,\s*0x[a-f\d]{2}\s*\}\s*}/gi; - -export const REGEX_PCD = /(?:\w[\w\d\[\]]+\.)+[\w\d\[\]]+/gi; - -export const REGEX_INF_SECTION = /(?.*?)(\.(?.*))?$/m; - diff --git a/src/edkParser/decParser.ts b/src/edkParser/decParser.ts deleted file mode 100644 index 024373e..0000000 --- a/src/edkParser/decParser.ts +++ /dev/null @@ -1,291 +0,0 @@ - -import * as vscode from 'vscode'; -import { BlockParser, DocumentParser } from "./languageParser"; -import path = require("path"); -import { Edk2SymbolType } from '../symbols/symbolsType'; -import { REGEX_ANY_BUT_SECTION, REGEX_DEFINE, REGEX_GUID, REGEX_INCLUDE, REGEX_PATH_FILE, REGEX_PATH_FOLDER } from './commonParser'; - - - - - - -class BlockComponentInf extends BlockParser { - name= "ComponentInf"; - tag= /^[\s\.\w\$\(\)_\-\\\/]*\.inf/gi; - start= /.*?{/; - end= /(^\})|(^\[)|(^[\s\.\w\$\(\)_\-\\\/]*\.inf)|(^\!include)/gi; - type= Edk2SymbolType.dscModuleDefinition; - - visible:boolean = true; - context: BlockParser[] = [ - new BlocklibraryDef(), - new BlockPcd(), - ]; -} - -class BlockComponentsSection extends BlockParser { - name= "Components"; - tag= /\[\s*components.*?\]/gi; - start= undefined; - end= /^\[/gi; - type= Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockComponentInf(), - - - - ]; - -} - - -class BlocklibraryDef extends BlockParser { - - name= "Library"; - tag= REGEX_PATH_FILE; - start= undefined; - end= undefined; - type= Edk2SymbolType.decLibrary; - visible:boolean = true; - - -} - - - - - -class BlockDefinition extends BlockParser { - - name= "Definition"; - tag= REGEX_DEFINE; - start = undefined; - end = undefined; - type= Edk2SymbolType.dscDefine; - visible:boolean = true; - -} - - - -// -// Main sections -// - -class BlockDefines extends BlockParser { - name= "Defines"; - tag= /\[\s*(defines|buildoptions)\s*\]/gi; - start= undefined; - end= /^\[/gi; - type= Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockDefinition(), - ]; -} - - -class BlockSkuIds extends BlockParser { - - name = "SkuIds"; - tag = /\[\s*(skuids)\s*\]/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - - ]; - - - -} - -class BlockLibraryClasses extends BlockParser { - - name = "LibraryClasses"; - tag = /\[\s*libraryclasses.*?\]/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlocklibraryDef(), - - ]; - -} - - - -class BlockPcd extends BlockParser { - name = "Pcds"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.decPcd; - visible:boolean = true; - context: BlockParser[] = []; - -} - -class BlockPcdSection extends BlockParser { - name = "PcdSection"; - tag = /\[\s*pcds.*?\]/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPcd(), - - ]; -} - - -class BlockGenericSection extends BlockParser { - name = "SectionUnknown"; - tag = /\[/gi; - start = undefined; - end = /\[/gi; - type = Edk2SymbolType.unknown; - visible:boolean = true; - context: BlockParser[] = [ - - ]; - - -} - - - -class BlockInclude extends BlockParser { - - name= "Include"; - tag= REGEX_PATH_FOLDER; - excludeTag = undefined; - start= undefined; - end= undefined; - type= Edk2SymbolType.decInclude; - visible:boolean = true; - -} - -class BlockIncludeSection extends BlockParser { - name = "Includes"; - tag = /\[\s*includes.*?\]/gi; - start = undefined; - end = /\[/gi; - type = Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockInclude(), - ]; - - -} - - - -class BlockGuid extends BlockParser { - - name= "Guid"; - tag= REGEX_ANY_BUT_SECTION; - excludeTag = undefined; - start= undefined; - end= undefined; - type= Edk2SymbolType.decGuid; - visible:boolean = true; - -} -class BlockGuidsSection extends BlockParser { - name = "Guids"; - tag = /\[\s*Guids.*?\]/gi; - start = undefined; - end = /\[/gi; - type = Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockGuid(), - ]; - - -} - -class BlockProtocol extends BlockParser { - - name= "Protocol"; - tag= REGEX_GUID; - excludeTag = undefined; - start= undefined; - end= undefined; - type= Edk2SymbolType.decProtocol; - visible:boolean = true; - -} -class BlockProtocolsSection extends BlockParser { - name = "Protocols"; - tag = /\[\s*Protocols.*?\]/gi; - start = undefined; - end = /\[/gi; - type = Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockProtocol(), - ]; - - -} - - -class BlockPpi extends BlockParser { - - name= "Ppi"; - tag= REGEX_ANY_BUT_SECTION; - excludeTag = undefined; - start= undefined; - end= undefined; - type= Edk2SymbolType.decPpi; - visible:boolean = true; - -} -class BlockPpisSection extends BlockParser { - name = "Ppis"; - tag = /\[\s*Ppis.*?\]/gi; - start = undefined; - end = /\[/gi; - type = Edk2SymbolType.decSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPpi(), - ]; - - -} - - - -export class DecParser extends DocumentParser { - - commentStart: string = "/*"; - commentEnd: string = "*/"; - commentLine: string[] = ["#"]; - - privateDefines: Map = new Map(); - - blockParsers: BlockParser[] = [ - new BlockDefines(), - new BlockIncludeSection(), - new BlockGuidsSection(), - new BlockProtocolsSection(), - new BlockPpisSection(), - new BlockLibraryClasses(), - new BlockPcdSection(), - new BlockGenericSection(), - - ]; - -} - diff --git a/src/edkParser/dscParser.ts b/src/edkParser/dscParser.ts deleted file mode 100644 index 395ad71..0000000 --- a/src/edkParser/dscParser.ts +++ /dev/null @@ -1,298 +0,0 @@ - -import * as vscode from 'vscode'; -import { BlockParser, DocumentParser } from "./languageParser"; -import path = require("path"); -import { Edk2SymbolType } from '../symbols/symbolsType'; -import { REGEX_DEFINE, REGEX_INCLUDE } from './commonParser'; - - -export const UNDEFINED_VARIABLE = "???"; - -class BlockIncludes extends BlockParser { - name = "Include"; - type = Edk2SymbolType.dscInclude; - tag = REGEX_INCLUDE; - start = undefined; - end = undefined; - visible:boolean = true; -} - - - -class BlockBuildOption extends BlockParser { - name = "BuildOption"; - tag = /^[\w\*\:\|]+\s*=\s*.*/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.dscBuildOption; - visible: boolean = true; -} - -class BlockComponentSubLibraryClasses extends BlockParser { - name = "ComponentLibraryClasses"; - tag = /^<\s*LibraryClasses\s*>/gi; - start = undefined; - end = /(^<)|(^\})/gi; - type = Edk2SymbolType.dscComponentSubSection; - visible: boolean = true; - context: BlockParser[] = [ - new BlocklibraryDef(), - new BlockIncludes(), - ]; -} - -class BlockComponentSubPcds extends BlockParser { - name = "ComponentPcds"; - tag = /^<\s*Pcd[^>]*>/gi; - start = undefined; - end = /(^<)|(^\})/gi; - type = Edk2SymbolType.dscComponentSubSection; - visible: boolean = true; - context: BlockParser[] = [ - new BlockPcd(), - new BlockIncludes(), - ]; -} - -class BlockComponentSubBuildOptions extends BlockParser { - name = "ComponentBuildOptions"; - tag = /^<\s*BuildOptions\s*>/gi; - start = undefined; - end = /(^<)|(^\})/gi; - type = Edk2SymbolType.dscComponentSubSection; - visible: boolean = true; - context: BlockParser[] = [ - new BlockBuildOption(), - new BlockIncludes(), - ]; -} - -class BlockComponentInf extends BlockParser { - name= "ComponentInf"; - tag= /^[\s\.\w\$\(\)_\-\\\/]*\.inf/gi; - start= /.*?{/; - end= /(^\})|(^\[)|(^[\s\.\w\$\(\)_\-\\\/]*\.inf)|(^\!include)/gi; - type= Edk2SymbolType.dscModuleDefinition; - startContext= /\{/; - endContext= /^\s*\}/gi; - - visible:boolean = true; - context: BlockParser[] = [ - new BlockComponentSubLibraryClasses(), - new BlockComponentSubPcds(), - new BlockComponentSubBuildOptions(), - // new BlocklibraryDef(), - // new BlockPcd(), - ]; -} - -class BlockComponentsSection extends BlockParser { - name= "Components"; - tag= /\[\s*components.*?\]/gi; - start= undefined; - end= /^\[/gi; - type= Edk2SymbolType.dscSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockComponentInf(), - - new BlockIncludes(), - - - ]; - - - - -} - - - -class BlocklibraryDef extends BlockParser { - - name= "libraryDef"; - tag= /^\w*\s*\|\s*[\s\.\w\$\(\)_\-\\\/]*\.inf/gi; - start= undefined; - end= undefined; - type= Edk2SymbolType.dscLibraryDefinition; - visible:boolean = true; - - -} - -class BlockflashDefinition extends BlockParser { - - - name= "flashDefinition"; - tag= /^flash_definition\s*\=\s*.*/gi; - start= undefined; - end= undefined; - type= Edk2SymbolType.dscLibraryDefinition; - visible:boolean = true; - -} - - - -class BlockDefinition extends BlockParser { - - name= "Definition"; - tag= REGEX_DEFINE; - start = undefined; - end = undefined; - type= Edk2SymbolType.dscDefine; - visible:boolean = true; - -} - -class BlockSimpleLine extends BlockParser { - - name= "Text"; - tag= /.*/gi; - excludeTag = /^\[/gi; - start= undefined; - end= undefined; - type= Edk2SymbolType.unknown; - visible:boolean = true; - -} - -// -// Main sections -// - -class BlockBuildOptionsSection extends BlockParser { - name = "BuildOptions"; - tag = /\[\s*buildoptions.*?\]/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.dscBuildOptionsSection; - visible: boolean = true; - context: BlockParser[] = [ - new BlockBuildOption(), - new BlockIncludes(), - ]; -} - -class BlockDefines extends BlockParser { - name= "Defines"; - tag= /\[\s*defines\s*\]/gi; - start= undefined; - end= /^\[/gi; - type= Edk2SymbolType.dscSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockflashDefinition(), - new BlockDefinition(), - new BlockIncludes(), - - ]; -} - - -class BlockSkuIds extends BlockParser { - - name = "SkuIds"; - tag = /\[\s*(skuids)\s*\]/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.dscSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockIncludes(), - - ]; - - - -} - -class BlockLibraryClasses extends BlockParser { - - name = "LibraryClasses"; - tag = /\[\s*libraryclasses.*?\]/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.dscSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlocklibraryDef(), - new BlockIncludes(), - - ]; - -} - - - -class BlockPcd extends BlockParser { - name = "Pcds"; - tag = /.*?\..*?\|.*$/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.dscPcdDefinition; - visible:boolean = true; - context: BlockParser[] = []; - -} - -class BlockPcdSection extends BlockParser { - name = "PcdSection"; - tag = /\[\s*pcds.*?\]/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.dscSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPcd(), - new BlockIncludes(), - - ]; -} - -class BlockGenericSection extends BlockParser { - name = "SectionUnknown"; - tag = /\[/gi; - start = undefined; - end = /\[/gi; - type = Edk2SymbolType.unknown; - visible:boolean = true; - context: BlockParser[] = [ - new BlockIncludes(), - - ]; - - -} - - - -export class DscParser extends DocumentParser { - - commentStart: string = "/*"; - commentEnd: string = "*/"; - commentLine: string[] = ["#"]; - - privateDefines: Map = new Map(); - - blockParsers: BlockParser[] = [ - new BlockDefines(), - new BlockBuildOptionsSection(), - new BlockComponentsSection(), - new BlockLibraryClasses(), - new BlockSkuIds(), - new BlockPcdSection(), - new BlockGenericSection(), - - new BlockDefinition(true), - new BlockIncludes(true), - new BlockComponentInf(true), - new BlocklibraryDef(true), - new BlockPcd(true), - new BlockBuildOption(true), - ]; - - - - -} diff --git a/src/edkParser/fdfParser.ts b/src/edkParser/fdfParser.ts deleted file mode 100644 index 85a2490..0000000 --- a/src/edkParser/fdfParser.ts +++ /dev/null @@ -1,142 +0,0 @@ - -import { Edk2SymbolType } from "../symbols/symbolsType"; -import { createRange, split } from "../utils"; -import { REGEX_DEFINE, REGEX_INCLUDE } from "./commonParser"; -import { BlockParser, DocumentParser } from "./languageParser"; - -class BlockIncludes extends BlockParser { - name = "Include"; - type = Edk2SymbolType.fdfInclude; - tag = REGEX_INCLUDE; - start = undefined; - end = undefined; - visible:boolean = true; -} - -class BlockAprioriInf extends BlockParser { - name= "Apriori"; - tag= /APRIORI \w+/gi; - start= /.*?{/; - end= /(^\})|(^\!include)/gi; - type= Edk2SymbolType.unknown; - - visible:boolean = true; - context: BlockParser[] = [ - new BlockComponentInf(), - ]; -} - - -class BlockComponentInf extends BlockParser { - name= "ComponentInf"; - tag= /^INF\s+[\s\.\w\$\(\)_\-\\\/]*\.inf/gi; - start= undefined; - end= undefined; - type= Edk2SymbolType.fdfInf; - - visible:boolean = true; -} - -class BlockSimpleLine extends BlockParser { - - name= "Text"; - tag= /.*/gi; - excludeTag = /^\[/gi; - start= undefined; - end= undefined; - type= Edk2SymbolType.unknown; - visible:boolean = true; - -} - -class BlockDefinition extends BlockParser { - name= "Definition"; - tag= REGEX_DEFINE; - start = undefined; - end = undefined; - type= Edk2SymbolType.fdfDefinition; - visible:boolean = true; - -} - -class BlockFV extends BlockParser { - name = "FV"; - tag = /^\[\s*FV\./gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.fdfSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockComponentInf(), - new BlockAprioriInf(), - new BlockDefinition(), - new BlockIncludes(), - new BlockSimpleLine(), - ]; -} - -class BlockFd extends BlockParser { - name = "FD"; - tag = /^\[\s*FD\./gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.fdfSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockDefinition(), - new BlockIncludes(), - new BlockSimpleLine(), - ]; -} - -class BlockRuleSection extends BlockParser { - name = "Rule"; - tag = /^\[\s*Rule\./gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.fdfSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockIncludes(), - new BlockSimpleLine(), - ]; -} - - -class BlockGenericSection extends BlockParser { - name = "SectionUnknown"; - tag = /\[/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.dscSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockIncludes(), - new BlockSimpleLine() - ]; -} - - - -export class FdfParser extends DocumentParser { - - commentStart: string = "/*"; - commentEnd: string = "*/"; - commentLine: string[] = ["#"]; - - privateDefines: Map = new Map(); - - blockParsers: BlockParser[] = [ - new BlockFV(), - new BlockFd(), - new BlockRuleSection(), - new BlockGenericSection(), - - new BlockComponentInf(true), - new BlockIncludes(true), - ]; - - - - -} \ No newline at end of file diff --git a/src/edkParser/infParser.ts b/src/edkParser/infParser.ts deleted file mode 100644 index 9b00b53..0000000 --- a/src/edkParser/infParser.ts +++ /dev/null @@ -1,368 +0,0 @@ - -import { debuglog } from "util"; -import { Edk2SymbolType, typeToStr } from "../symbols/symbolsType"; -import { createRange, split } from "../utils"; -import { REGEX_ANY_BUT_SECTION, REGEX_DEFINE } from "./commonParser"; -import { BlockParser, DocumentParser } from "./languageParser"; -import { EdkSymbol } from "../symbols/edkSymbols"; -import * as vscode from 'vscode'; -import { DiagnosticManager, EdkDiagnosticCodes } from "../diagnostics"; - -class BlockModuleType extends BlockParser { - name= "ModuleType"; - tag= /MODULE_TYPE\s*\=/gi; - start = undefined; - end = undefined; - type= Edk2SymbolType.infDefine; - visible:boolean = true; -} - -class BlockBaseName extends BlockParser { - name= "BaseName"; - tag= /BASE_NAME\s*\=/gi; - start = undefined; - end = undefined; - type= Edk2SymbolType.infDefine; - visible:boolean = true; -} - -class BlockEntryPoint extends BlockParser { - name= "EntryPoint"; - tag= /ENTRY_POINT\s*\=/gi; - start = undefined; - end = undefined; - type= Edk2SymbolType.infDefine; - visible:boolean = true; -} - -class BlockLibraryClass extends BlockParser { - name= "LibraryClass"; - tag= /LIBRARY_CLASS\s*\=/gi; - start = undefined; - end = undefined; - type= Edk2SymbolType.infDefine; - visible:boolean = true; -} - -class BlockConstructor extends BlockParser { - name= "Constructor"; - tag= /CONSTRUCTOR\s*\=/gi; - start = undefined; - end = undefined; - type= Edk2SymbolType.infDefine; - visible:boolean = true; -} - -class BlockDestructor extends BlockParser { - name= "Destructor"; - tag= /DESTRUCTOR\s*\=/gi; - start = undefined; - end = undefined; - type= Edk2SymbolType.infDefine; - visible:boolean = true; -} - -class BlockDefinition extends BlockParser { - name= "Definition"; - tag= REGEX_DEFINE; - start = undefined; - end = undefined; - type= Edk2SymbolType.infDefine; - visible:boolean = true; -} - -class BlockDefinesSection extends BlockParser { - name = "Defines"; - tag = /^\[\s*Defines/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSection; - visible:boolean = true; - context: BlockParser[] = [ - - new BlockModuleType(), - new BlockBaseName(), - new BlockEntryPoint(), - new BlockLibraryClass(), - new BlockConstructor(), - new BlockDestructor(), - new BlockDefinition(), - new BlockSimpleLine(), - ]; -} - - -class BlockSource extends BlockParser { - name = "Source"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infSource; - visible:boolean = true; - -} -class BlockSourcesSection extends BlockParser { - name = "Sources"; - tag = /^\[\s*Sources/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionSource; - visible:boolean = true; - context: BlockParser[] = [ - new BlockSource(), - new BlockSimpleLine(), - ]; -} - - -class BlockPackage extends BlockParser { - name = "Package"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infPackage; - visible:boolean = true; - -} -class BlockPackagesSection extends BlockParser { - name = "Packages"; - tag = /^\[\s*Packages/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionPackages; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPackage(), - new BlockSimpleLine(), - ]; -} - - -class BlockLibrary extends BlockParser { - name = "Library"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infLibrary; - visible:boolean = true; -} - -class BlockLibraryClassesSection extends BlockParser { - name = "LibraryClasses"; - tag = /^\[\s*LibraryClasses/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionLibraries; - visible:boolean = true; - context: BlockParser[] = [ - new BlockLibrary(), - new BlockSimpleLine(), - ]; -} - -class BlockGuid extends BlockParser { - name = "Guid"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infGuid; - visible:boolean = true; - diagnostic = async (docParser:DocumentParser, symbol:EdkSymbol)=>{ - if(!await symbol.isInDec(Edk2SymbolType.decGuid)){ - DiagnosticManager.error(docParser.document.uri, symbol.range, EdkDiagnosticCodes.statementNoKey, `No ${typeToStr.get(this.type)} found for ${symbol.name} in .dec files`); - } - }; -} - -class BlockDepex extends BlockParser { - name = "Depex"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infDepex; - visible:boolean = true; - -} - -class BlockGuidsSection extends BlockParser { - name = "Guids"; - tag = /^\[\s*Guids/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionGuids; - visible:boolean = true; - context: BlockParser[] = [ - new BlockGuid(), - new BlockSimpleLine(), - ]; -} - - -class BlockProtocol extends BlockParser { - name = "Protocol"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infProtocol; - visible:boolean = true; - diagnostic = async (docParser:DocumentParser, symbol:EdkSymbol)=>{ - if(!await symbol.isInDec(Edk2SymbolType.decProtocol)){ - DiagnosticManager.error(docParser.document.uri, symbol.range, EdkDiagnosticCodes.statementNoKey, `No ${typeToStr.get(this.type)} found for ${symbol.name} in .dec files`); - } - }; -} - -class BlockProtocolsSection extends BlockParser { - name = "Protocols"; - tag = /^\[\s*Protocols/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionProtocols; - visible:boolean = true; - context: BlockParser[] = [ - new BlockProtocol(), - new BlockSimpleLine(), - ]; -} - -class BlockPpi extends BlockParser { - name = "Ppi"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infPpi; - visible:boolean = true; - diagnostic = async (docParser:DocumentParser, symbol:EdkSymbol)=>{ - if(!await symbol.isInDec(Edk2SymbolType.decPpi)){ - DiagnosticManager.error(docParser.document.uri, symbol.range, EdkDiagnosticCodes.statementNoKey, `No ${typeToStr.get(this.type)} found for ${symbol.name} in .dec files`); - } - }; -} - -class BlockPpisSection extends BlockParser { - name = "Ppi"; - tag = /^\[\s*Ppis/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionPpis; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPpi(), - ]; -} - -class BlockPcd extends BlockParser { - name = "Pcd"; - tag = REGEX_ANY_BUT_SECTION; - start = undefined; - end = undefined; - type = Edk2SymbolType.infPcd; - visible:boolean = true; - diagnostic = async (docParser:DocumentParser, symbol:EdkSymbol)=>{ - if(!await symbol.isInDec(Edk2SymbolType.decPcd)){ - DiagnosticManager.error(docParser.document.uri, symbol.range, EdkDiagnosticCodes.statementNoKey, `No ${typeToStr.get(this.type)} found for ${symbol.name} in .dec files`); - } - }; -} - -class BlockPcdSection extends BlockParser { - name = "Pcd"; - tag = /^\[\s*(feature|fixed)?Pcd/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionPcds; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPcd(), - new BlockSimpleLine(), - ]; -} - -class BlockDepexSection extends BlockParser { - name = "Depex"; - tag = /^\[\s*Depex/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSectionDepex; - visible:boolean = true; - context: BlockParser[] = [ - new BlockDepex(), - ]; -} - -class BlockSimpleLine extends BlockParser { - name= "Text"; - tag= REGEX_ANY_BUT_SECTION; - excludeTag = /^\[/gi; - start= undefined; - end= undefined; - type= Edk2SymbolType.unknown; - visible:boolean = true; -} - -class BlockGenericSection extends BlockParser { - name = "SectionUnknown"; - tag = /\[/gi; - start = undefined; - end = /^\[/gi; - type = Edk2SymbolType.infSection; - visible:boolean = true; - context: BlockParser[] = [ - new BlockSimpleLine() - ]; -} - -export class InfParser extends DocumentParser { - commentStart: string = "/*"; - commentEnd: string = "*/"; - commentLine: string[] = ["#"]; - - blockParsers: BlockParser[] = [ - - new BlockSourcesSection(), - new BlockPackagesSection(), - new BlockLibraryClassesSection(), - new BlockGuidsSection(), - new BlockPpisSection(), - new BlockProtocolsSection(), - new BlockPcdSection(), - new BlockDepexSection(), - - new BlockDefinesSection(), - new BlockGenericSection(), -]; - - isLibrary(){ - if(this.document.getText().match(/^\s*library_class\s*=/gmi)){ - return true; - } - return false; - } -} - -// export class XInfParser extends LanguageParser { - -// blockParsers: BlockParser[] = []; -// commentStart: string = "/*"; -// commentEnd: string = "*/"; -// commentLine: string[] = ["#"]; - - - // blocks: any[] = [ - // {name:"Packages", tag: /\[\s*(packages.*?)\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSection, inBlockFunction:this.blockParserPath, childType:Edk2SymbolType.infPackage}, - // {name:"Sources", tag: /\[\s*(sources.*?)\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSection, inBlockFunction:this.blockParserPath, childType:Edk2SymbolType.infSource}, - // {name:"Defines", tag: /\[\s*(defines.*?)\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSection, inBlockFunction:this.blockParserBinary, binarySymbol: "=", childType:Edk2SymbolType.infDefine}, - // {name:"Libraryclasses", tag: /\[\s*libraryclasses.*?\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSectionLibraries, inBlockFunction:this.blockParserLine, childType:Edk2SymbolType.infLibrary}, - // {name:"Definition", tag: /^define .+/gi, start: undefined, end: undefined, type:Edk2SymbolType.infDefine, produce:this.produceDefine}, - // {name:"Protocols", tag: /\[\s*protocols.*?\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSectionProtocols, inBlockFunction:this.blockParserLine, childType:Edk2SymbolType.infProtocol}, - // {name:"Ppis", tag: /\[\s*ppis.*?\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSectionPpis, inBlockFunction:this.blockParserLine, childType:Edk2SymbolType.infPpi}, - // {name:"Guids", tag: /\[\s*guids.*?\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSectionGuids, inBlockFunction:this.blockParserLine, childType:Edk2SymbolType.infGuid}, - // {name:"Pcd", tag: /\[\s*(fixed)?pcd.*?\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSectionPcds, inBlockFunction:this.blockParserLine, childType:Edk2SymbolType.infPcd}, - // {name:"Binaries", tag: /\[\s*(binaries.*?)\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSection, inBlockFunction:this.blockParserLine, childType:Edk2SymbolType.infBinary}, - // {name:"depex", tag: /\[\s*(depex.*?)\s*\]/gi, start: undefined, end: /^\[/gi, type:Edk2SymbolType.infSection, inBlockFunction:this.blockParserLine, childType:Edk2SymbolType.infDepex}, - // ]; - - - - -// } \ No newline at end of file diff --git a/src/edkParser/languageParser.ts b/src/edkParser/languageParser.ts deleted file mode 100644 index 3a70c84..0000000 --- a/src/edkParser/languageParser.ts +++ /dev/null @@ -1,544 +0,0 @@ - -import { gDebugLog } from "../extension"; -import * as vscode from 'vscode'; -import path = require("path"); -import { SymbolFactory } from "../symbols/symbolFactory"; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import { WorkspaceDefinitions } from "../index/definitions"; -import { EdkSymbol } from "../symbols/edkSymbols"; -import { SectionProperties } from "../index/edkWorkspace"; - - -export abstract class BlockParser { - abstract name: string; // Name of the block parser - abstract tag: RegExp; // Regular expression to match the block tag - abstract start: RegExp | undefined; // Regular expression to match the start of the block content - abstract end: RegExp | undefined; // Regular expression to match the end of the block content - abstract type: Edk2SymbolType; // Type of the block parser - excludeTag: RegExp | undefined; // Regular expression to exclude specific tags - context: BlockParser[] = []; // Array of block parsers that can be nested inside this block parser - abstract visible: boolean; // Indicates if the block is visible or hidden - exclusive: boolean = true; // Indicates if other blocks should parse this line - isRoot: boolean = false; // Indicates if this block is in the root block of the document - diagnostic: undefined | ((docParser:DocumentParser, symbol:EdkSymbol) => Promise) = undefined; - startContext: RegExp | undefined; // When matched during start phase, endContext replaces end for block termination - endContext: RegExp | undefined; // End pattern used when startContext was matched - - constructor(isRoot: boolean = false) { - this.isRoot = isRoot; - } - - /** - * The `parse` function is used to parse a document using a defined DocumentParser. - * - * @param {DocumentParser} docParser - An instance of a DocumentParser that will be used to parse the content. - * @returns {boolean} - Returns true if the parsing was successful, false otherwise. - */ - parse(docParser: DocumentParser) { - // Check if line matches - const currentIndex = docParser.lineIndex; - - let textLine = docParser.getNextLineTextUncomment(); - if (textLine === undefined || textLine.length === 0) { - return false; - } - - if (this.excludeTag && textLine.match(this.excludeTag)) { - return false; - } - - - - if (textLine.match(this.tag)) { - gDebugLog.trace(`New block ${this.name} (${this.tag.toString()} -> ${textLine})`); - - // Check if symbol is root definition - if (this.isRoot && !docParser.isInRoot()) { - return false; - } - - const line = docParser.getLineAt(currentIndex); - if (!line) { - gDebugLog.error(`Wrong line: ${currentIndex} at ${docParser.document.fileName}`); - return; - } - - const range = new vscode.Range(line.range.start, new vscode.Position(docParser.document.lineCount, 0)); - const symbolFactory = new SymbolFactory(); - const location = new vscode.Location(docParser.document.uri, range); - - const symbol = symbolFactory.produceSymbol(this.type, textLine, location, docParser); - - if (!symbol) { - return false; - } - - docParser.addSymbol(symbol); - docParser.pushSymbolStack(symbol); - - - if (this.diagnostic) { - setTimeout(async () => { - await this.diagnostic!(docParser, symbol); - }, 1); // Adjust the delay (in milliseconds) as needed - } - - // Check if context mode is active (startContext matched on the tag line) - let inContext = false; - if (this.startContext && textLine.match(this.startContext)) { - inContext = true; - } - - // look for block start - if (this.start) { - // read lines until start tag is found - while (!textLine.match(this.start)) { - - if (this.end && textLine.match(this.end)) { - docParser.popSymbolStack(); - return true; - } - - textLine = docParser.getNextLineTextUncomment(); - if (textLine === undefined) { - docParser.popSymbolStack(); - return true; - } - // Check startContext on lines scanned for block start - if (!inContext && this.startContext && textLine.match(this.startContext)) { - inContext = true; - } - } - } else { - if (this.end === undefined) { - docParser.popSymbolStack(); - return true; - } - } - - // Use endContext instead of end when context mode is active - const activeEnd = inContext && this.endContext ? this.endContext : this.end; - - // Parse block content - while (docParser.hasPendingLines()) { - // create a symbol - textLine = docParser.getNextLineTextUncomment(); - - if (textLine === undefined) { - gDebugLog.error("Wrong Line in parser"); - return; - } - if (textLine.length === 0) { - continue; - } - - // parse block - let contextMatched = false; - const contextLength = this.context.length; - for (let i = 0; i < contextLength; i++) { - const blockContext = this.context[i]; - gDebugLog.trace(`Parse block: ${blockContext.name}`); - // decrement line index as parser will get next line by default - docParser.decrementLineIndex(); - const isSymbolAdded = blockContext.parse(docParser); - if (isSymbolAdded) { - gDebugLog.trace("Added symbol"); - contextMatched = true; - if (blockContext.exclusive) { - break; - } - } - } - - // If a context parser consumed lines, peek at the last consumed line - // to check if it also matches our endContext (child may have consumed the delimiter) - if (contextMatched && inContext && this.endContext) { - const peekIdx = docParser.lineIndex - 1; - if (peekIdx >= 0 && peekIdx < docParser.document.lineCount) { - const peekText = docParser.removeComment( - docParser.document.lineAt(peekIdx).text - ); - if (peekText.match(this.endContext)) { - docParser.popSymbolStack(); - return true; - } - } - } - - // Check the end tag - if (activeEnd && textLine.match(activeEnd)) { - docParser.popSymbolStack(); - return true; - } - } - - docParser.popSymbolStack(); - return true; - } - - return false; - } - - _debug() { } - - -} - - - - -export class DocumentParser { - document: vscode.TextDocument; // The text document to parse - lineIndex: number = 1; // Current line index for parsing - - commentStart: string = ""; // Start of a comment block - commentEnd: string = ""; // End of a comment block - commentLine: string[] = []; // Array to store individual lines of a comment - inComment: boolean = false; // Flag to track if currently inside a comment block - - blockParsers: BlockParser[] = []; // Array of block parsers - - symbolsTree: EdkSymbol[] = []; // Tree structure to store parsed symbols - symbolsList: EdkSymbol[] = []; // Flat list of parsed symbols - symbolStack: EdkSymbol[] = []; // Stack to track the nesting of symbols - - defines: WorkspaceDefinitions = new WorkspaceDefinitions(); // Definitions for the workspace - - constructor(document: vscode.TextDocument) { - this.document = document; - this.lineIndex = 0; - } - - /** - * Checks if the current line is a comment. - * - * @returns Returns true if the current line is a comment, otherwise false. - */ - isLineComment() { - // Get the text of the current line - let line = this.document.lineAt(this.lineIndex - 1).text; - - // Remove any comment from the line - line = this.removeComment(line); - - // If the line is empty after removing the comment, it is a comment line - if (line === "") { - return true; - } - - // If the line is not empty after removing the comment, it is not a comment line - return false; - } - - /** - * Method to retrieve a specific line from a document. - * - * @returns {string|undefined} The retrieved line from the document, or undefined if the current index exceeds the document's line count. - */ - getLine() { - // check if the line index is greater than or equal to the number of lines in the document - if (this.lineIndex >= this.document.lineCount) { - // if true, return undefined since no line exists at this index position - return undefined; - } - - // if the line index is less, get that line from the document using the lineAt() method - let line = this.document.lineAt(this.lineIndex); - // return the retrieved line. - return line; - } - - /** - * This function is used to get the line at a specific index from a document. - * It retrieves the line of text using the lineAt method of the document's object. - * - * @param index - A number representing the index of the desired line in the document. - * Zero-based index numbers should be used, meaning the first line of the document is at index 0. - * - * @returns - Returns a `line` object at the specified index. If the index is out of bounds of the document, it will return undefined. - */ - getLineAt(index: number) { - let line = this.document.lineAt(index); - return line; - } - -/** - * This function checks if there are any pending lines left in the document that have not been processed. - * - * @returns {boolean} It returns `true` if there is a pending line to be processed, `false` otherwise. - */ - hasPendingLines(): boolean { - return this.lineIndex < this.document.lineCount; - } - - /** - * Return the next line without comments. - * Increment the line index to prepare for the next line. - */ - getNextLineTextUncomment() { - let line = this.getLineTextUncomment(); - this.incrementLineIndex(); - return line; - } - - /** - * Gets the text of the current line without comments. - * If the line index is out of range, returns undefined. - */ - getLineTextUncomment() { - if (this.lineIndex >= this.document.lineCount) { - return undefined; - } - - let line = this.document.lineAt(this.lineIndex).text; - line = this.removeComment(line); - - return line; - } - - /** - * Function to get the current line index. - * - * This function will return the index of the current line in the document - * being processed. This is especially useful when needing to keep track - * of the current position within a document while processing it. - * - * @returns {number} The index of the current line in the document. - */ - getLineIndex() { - return this.lineIndex; - } - - /** - * The `incrementLineIndex` function increases the `lineIndex` property by one. - * This can be used to manually navigate through the lines of a document. - */ - incrementLineIndex() { - this.lineIndex++; - } - - /** - * Decreases the line index by one. - * This allows you to move the line index pointer to the previous line in the document. - */ - decrementLineIndex() { - if(this.lineIndex === 0){ - gDebugLog.error("LineIndex already 0"); - return; - } - this.lineIndex--; - } - - /** - * Removes comment from the given line - * @param line - The line of code to remove comments from - * @returns The line of code without comments - */ - removeComment(line: string) { - // Iterate over each comment line and remove comments - for (const comment of this.commentLine) { - line = line.trim().split(comment)[0].trim(); // Remove comment substring - } - - // Check if the line starts with the comment start marker - if (line.startsWith(this.commentStart)) { - this.inComment = true; // Set inComment flag to indicate line in a comment block - } - // Check if the line ends with the comment end marker - if (line.endsWith(this.commentEnd)) { - this.inComment = false; // Set inComment flag to indicate end of comment block - } - - // Check if the line is inside a comment block - if (this.inComment) { - return ""; // Empty string indicates line is a comment - } - return line; // Return the line without comments - } - - /** - * This function adds a new symbol to the symbol stack. - * - * @param {EdkSymbol} symbol - The input symbol to be added to the symbol stack - * @returns {void} - */ - pushSymbolStack(symbol: EdkSymbol) { - this.symbolStack.push(symbol); - } - - /** - * This function checks if the symbol stack is empty. - * - * @returns A boolean indication whether the symbol stack is empty or not. - * If it's empty, the function will return true, indicating the symbolStack is in the root. - * If it's not empty, the function will return false. - */ - isInRoot() { - return this.symbolStack.length === 0; - } - - /** - * Remove the last symbol from the symbol stack and adjust its range based on its children range. - * @returns The last symbol from the symbol stack after adjusting its range, or undefined if the symbol stack is empty. - */ - popSymbolStack() { - // Retrieve the last symbol from the symbol stack - let lastSymbol = this.symbolStack.pop(); - - // Check if the symbol stack is empty - if (lastSymbol === undefined) { - // Print an error message and return undefined - gDebugLog.error("Symbol stack is empty"); - return undefined; - } - - // Adjust the range of the symbol based on its children range - if (lastSymbol.children.length > 0) { - // Get the end position of the symbol based on the range of the line before the current line index - let end = lastSymbol.range.end; - let line = this.getLineAt(this.lineIndex - 2); - if (line) { - end = line.range.end; - } - - // Create a temporary range using the adjusted start and end positions - let tempRange = new vscode.Range(lastSymbol.range.start, end); - - // Update the range of the last symbol - lastSymbol.updateRange(tempRange); - } else { - // Get the end position of the symbol based on the range of the current line index - let end = lastSymbol.range.end; - let line = this.getLineAt(this.lineIndex - 1); - if (line) { - end = line.range.end; - } - - // Create a temporary range using the adjusted start and end positions - let tempRange = new vscode.Range(lastSymbol.range.start, end); - - // Update the range of the last symbol - lastSymbol.updateRange(tempRange); - } - - // Return the last symbol - return lastSymbol; - } - -/** - * This function adds a symbol to the tree structure. If the symbol stack is empty it means the symbol is a - * root. Otherwise, the symbol is a child of the last symbol that was pushed into the stack. - * - * @param symbol - The symbol to be added. - */ -addSymbol(symbol: EdkSymbol) { - if (this.symbolStack.length === 0) { - this.symbolsTree.push(symbol); - } else { - let lastSymbol = this.symbolStack[this.symbolStack.length - 1]; - lastSymbol.children.push(symbol); - symbol.parent = lastSymbol; - } - this.symbolsList.push(symbol); -} - - - /** - * This function is responsible for parsing a file by iterating through its lines. - * It skips lines that are comments, and calls the parseLine function for non-comment lines. - * It keeps track of the progress using the lineIndex variable. - * This function is asynchronous, indicating that it may involve additional operations that could delay its execution. - */ - async parseFile() { - // Log the start of the parsing process, including the file name - gDebugLog.info(`Parse Start: ${this.document.fileName}`); - - // Reset the line index to the first line of the document - this.lineIndex = 1; - - // Loop through each line of the document until reaching the line count - while (this.lineIndex < this.document.lineCount) { - // Check if the current line is not a line comment - if (!this.isLineComment()) { - // Parse the current non-comment line - await this.parseLine(); - } - - // Increment the line index to proceed to the next line - this.incrementLineIndex(); - } - - // Log the end of the parsing process, including the file name - gDebugLog.info(`Parse End: ${this.document.fileName}`); - } - - /** - * Asynchronously parse a line of code. - * This function iterates through all block parsers to parse the current line. - * If a line parsed correctly and it's not the root, this function will reset the parse index and attempt - * to perform additional parsing on the next line until no lines remain in the document. - * If the current line is in the root of the document, this function will continue parsing without changing the parse index. - * - * @async - */ - async parseLine() { - for (let parseIndex = 0; parseIndex < this.blockParsers.length; parseIndex++) { - const block = this.blockParsers[parseIndex]; - this.decrementLineIndex(); - let parserResult = block.parse(this); - if (parserResult) { - if (block.isRoot || (block.start === undefined && block.end === undefined)) { continue; } - parseIndex = -1; // reset index - if (this.lineIndex >= this.document.lineCount) { - return; - } - } - } - } - - /** - * Retrieves the symbol that contains the specified position. - * @param position The position to check for symbol containment. - * @returns The symbol that contains the position, or undefined if no symbol is found. - */ - getSelectedSymbol(position: vscode.Position) { - let selectedSymbol = undefined; - for (const symbol of this.symbolsList) { - if (symbol.range.contains(position)) { - selectedSymbol = symbol; - } - } - - return selectedSymbol; - } - - - /** - * Retrieves symbols of a specific type from the symbols list. - * - * @param type - The type of the symbols to retrieve. - * @returns An array of symbols of the specified type. - */ - getSymbolsType(type: Edk2SymbolType, filterContext: SectionProperties | undefined = undefined) { - - let symboList = Array.from(this.symbolsList.filter((x) => { return x.type === type; })); - if(filterContext){ - // Just keep the libraries that matches the context properties - symboList = symboList.filter((library)=>{ - if(library.sectionProperties.compareArchStr('common')){ - return true; - } - - if(filterContext){ - return library.sectionProperties.compareArch(filterContext); - } - return false; - - }); - } - return symboList; - } -} - - - diff --git a/src/edkParser/parserFactory.ts b/src/edkParser/parserFactory.ts deleted file mode 100644 index 8592184..0000000 --- a/src/edkParser/parserFactory.ts +++ /dev/null @@ -1,95 +0,0 @@ -import * as vscode from 'vscode'; -import { gDebugLog } from "../extension"; -import { DscParser } from "./dscParser"; -import { FdfParser } from "./fdfParser"; -import { InfParser } from "./infParser"; -import { DecParser } from './decParser'; -import { VfrParser } from './vfrParser'; -import { AslParser } from './aslParser'; -import { openTextDocument } from '../utils'; -import { DiagnosticManager } from '../diagnostics'; -import { Debouncer } from '../debouncer'; -import { DocumentParser } from './languageParser'; - -interface ParserCacheEntry { - parser: DocumentParser; - mtime: number; -} - -const parserCache = new Map(); - -export function invalidateParserCache(uri: vscode.Uri): void { - parserCache.delete(uri.toString()); -} - -export function clearParserCache(): void { - parserCache.clear(); -} - -/** - * Instantiates the appropriate parser for the given document based on its language ID. - * Returns `undefined` for unsupported language types. - */ -function createParserInstance(document: vscode.TextDocument): DocumentParser | undefined { - switch (document.languageId) { - case "asl": return new AslParser(document); - case "edk2_dsc": return new DscParser(document); - case "edk2_dec": return new DecParser(document); - case "edk2_vfr": return new VfrParser(document); - case "edk2_fdf": return new FdfParser(document); - case "edk2_inf": return new InfParser(document); - case "edk2_uni": return undefined; - default: - gDebugLog.error(`Document parser not supported: ${document.fileName}`); - return undefined; - } -} - -/** - * Returns a parsed `DocumentParser` for the given `TextDocument`. - * Results are cached by URI + mtime; if the file has not changed since the last - * parse the cached instance is returned immediately without re-parsing. - */ -export async function getParserForDocument(document: vscode.TextDocument): Promise { - const uri = document.uri; - const key = uri.toString(); - - // Retrieve the file modification time - let mtime: number | undefined; - try { - const stat = await vscode.workspace.fs.stat(uri); - mtime = stat.mtime; - } catch { - // File may not exist on disk (e.g. untitled); skip caching - } - - // Return cached parser when the file has not been modified - if (mtime !== undefined) { - const cached = parserCache.get(key); - if (cached && cached.mtime === mtime) { - gDebugLog.trace(`Parser cache hit: ${uri.fsPath}`); - return cached.parser; - } - } - - const parser = createParserInstance(document); - if (parser) { - await parser.parseFile(); - - // Store in cache only when we have a valid mtime - if (mtime !== undefined) { - parserCache.set(key, { parser, mtime }); - } - } - return parser; -} - -/** - * Convenience wrapper: opens the file at `uri` and returns its cached/parsed - * `DocumentParser`. Delegates to `getParserForDocument` after opening the document. - */ -export async function getParser(uri: vscode.Uri): Promise { - const document = await openTextDocument(uri); - return getParserForDocument(document); -} - diff --git a/src/edkParser/vfrParser.ts b/src/edkParser/vfrParser.ts deleted file mode 100644 index 9fc6155..0000000 --- a/src/edkParser/vfrParser.ts +++ /dev/null @@ -1,150 +0,0 @@ - -import { Edk2SymbolType } from "../symbols/symbolsType"; -import { createRange, split } from "../utils"; -import { REGEX_ANY_BUT_SECTION, REGEX_DEFINE } from "./commonParser"; -import { BlockParser, DocumentParser } from "./languageParser"; - - -class BlockFormsetSection extends BlockParser { - name = "Formset"; - tag = /\bformset\b/gi; - start = undefined; - end =/^endformset/gi; - type = Edk2SymbolType.vfrFormset; - visible:boolean = true; - context: BlockParser[] = [ - new BlockOneOfSection(), - new BlockNumericSection(), - new BlockCheckboxSection(), - new BlockCheckboxSection(), - new BlockStringSection(), - new BlockPasswordSection(), - new BlockGotoSection() - ]; -} - -class BlockFormSection extends BlockParser { - name = "Form"; - tag = /\bform\b/gi; - start = undefined; - end =/^endform/gi; - type = Edk2SymbolType.vfrForm; - visible:boolean = true; - context: BlockParser[] = [ - new BlockOneOfSection(), - new BlockNumericSection(), - new BlockCheckboxSection(), - new BlockCheckboxSection(), - new BlockStringSection(), - new BlockPasswordSection(), - new BlockGotoSection() - ]; -} - - -class BlockPrompt extends BlockParser { - name = "Prompt"; - tag = /\bprompt\b/gi; - start = undefined; - end =undefined; - type = Edk2SymbolType.vfrString; - visible:boolean = true; - context: BlockParser[] = [ - - ]; -} - -class BlockOneOfSection extends BlockParser { - name = "OneOf"; - tag = /\boneof\b/gi; - start = undefined; - end =/^endoneof/gi; - type = Edk2SymbolType.vfrOneof; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPrompt(), - ]; -} - -class BlockCheckboxSection extends BlockParser { - name = "Checkbox"; - tag = /\bcheckbox\b/gi; - start = undefined; - end =/^endcheckbox/gi; - type = Edk2SymbolType.vfrCheckbox; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPrompt(), - ]; -} - -class BlockStringSection extends BlockParser { - name = "String"; - tag = /\bstring\b/gi; - start = undefined; - end =/^endstring/gi; - type = Edk2SymbolType.vfrString; - visible:boolean = true; - context: BlockParser[] = [ - - ]; -} - -class BlockPasswordSection extends BlockParser { - name = "Password"; - tag = /\bpassword\b/gi; - start = undefined; - end =/^endpassword/gi; - type = Edk2SymbolType.vfrPassword; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPrompt(), - ]; -} - -class BlockNumericSection extends BlockParser { - name = "Numeric"; - tag = /\bnumeric\b/gi; - start = undefined; - end =/^endnumeric/gi; - type = Edk2SymbolType.vfrNumeric; - visible:boolean = true; - context: BlockParser[] = [ - new BlockPrompt(), - ]; -} - -class BlockGotoSection extends BlockParser { - name = "Goto"; - tag = /\bgoto\b/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.vfrGoto; - visible:boolean = true; - context: BlockParser[] = [ - - ]; -} - - -export class VfrParser extends DocumentParser { - commentStart: string = "/*"; - commentEnd: string = "*/"; - commentLine: string[] = ["//"]; - - blockParsers: BlockParser[] = [ - - new BlockFormsetSection(), - new BlockFormSection(), - new BlockOneOfSection(), - new BlockCheckboxSection(), - new BlockStringSection(), - new BlockPasswordSection(), - new BlockNumericSection(), - new BlockGotoSection(true), - -]; -} - - - diff --git a/src/extension.ts b/src/extension.ts deleted file mode 100644 index 0d09eb6..0000000 --- a/src/extension.ts +++ /dev/null @@ -1,429 +0,0 @@ -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below -import * as vscode from 'vscode'; -import * as path from 'path'; - -import { ConfigAgent } from './configuration'; -import { Cscope, CscopeAgent } from './cscope'; -import { DebugLog } from './debugLog'; -import * as edkStatusBar from './statusBar'; -import { FileUseWarning } from './usedFileTracker'; -import * as cmds from "./contextState/cmds"; - -import { initLanguages } from './Languages/languages'; -import { ModuleReport } from './moduleReport'; -import { GuidProvider } from './Languages/guidProvider'; -import { PathFind } from './pathfind'; -import { EdkWorkspaces } from './index/edkWorkspace'; -import { Edk2CallHierarchyProvider } from './callHiearchy'; -import { copyToClipboard, findClosestCommonDirectory, getCurrentDocument, getDocsUrl, gotoFile, showVirtualFile } from './utils'; -import { getParserForDocument } from './edkParser/parserFactory'; -import { DiagnosticManager } from './diagnostics'; -import { WorkspaceTreeProvider, WorkspaceRootItem, IncludeTreeItem, DocumentSymbolItem, WorkspaceTreeNode, isFileInWorkspaceTree, isInfInWorkspaces } from './workspaceTree/WorkspaceTreeProvider'; -import { InfDsc } from './index/edkWorkspace'; -import { MapFilesManager } from './mapParser'; -import { CompileCommands } from './compileCommands'; -import { compileCFile } from './compileFile'; -import { showReleaseNotes } from './newVersionPage/newVersionMessage'; -import { startMcpServer, stopMcpServer } from './mcp/mcpServer'; -import { DriverInfoTreeProvider } from './driverInfoTree/DriverInfoTreeProvider'; - - -// Global variables -// export var gEdkDatabase: EdkDatabase; -export var gPathFind = new PathFind(); -export var gEdkWorkspaces = new EdkWorkspaces(); -export var gCompileCommands:CompileCommands; - -export var gExtensionContext: vscode.ExtensionContext; -export var gWorkspacePath: string; -export var gConfigAgent:ConfigAgent; -export var gCscope:Cscope; -export var gCscopeAgent: CscopeAgent; // Agent to update cscope database -var gEdk2CallHierarchyProvider: Edk2CallHierarchyProvider; - -export var gDebugLog: DebugLog; -export var gFileUseWarning: FileUseWarning; - -export var gModuleReport: ModuleReport; -export var gGuidProvider:GuidProvider; -export var gDiagnosticManager:DiagnosticManager; - -export var edkWorkspaceTreeProvider: WorkspaceTreeProvider; -export var edkWorkspaceTreeView: vscode.TreeView; - -export var gDriverInfoTreeProvider: DriverInfoTreeProvider; - -export var gMapFileManager: MapFilesManager; - - -// this method is called when your extension is activated -// your extension is activated the very first time the command is executed -export async function activate(context: vscode.ExtensionContext) { - - if (vscode.workspace.workspaceFolders !== undefined) { - let workspacePaths = vscode.workspace.workspaceFolders.map(folder => folder.uri.fsPath); - gWorkspacePath = findClosestCommonDirectory(workspacePaths); - console.log(gWorkspacePath); - }else{ - return; - } - - gDebugLog = new DebugLog(); - gConfigAgent = new ConfigAgent(); - - gDebugLog.info("Start EDK2 Extension"); - gDebugLog.info("Workspace path: "+gWorkspacePath); - gDiagnosticManager = DiagnosticManager.getInstance(); - // By default start Context stage with offline commands - - - var commands = [ - vscode.commands.registerCommand('edk2code.rebuildIndex', async ()=>{await cmds.rebuildIndexDatabase();}), - vscode.commands.registerCommand('edk2code.useDiscoveredBuildFolders', async ()=>{await cmds.useDiscoveredBuildFolders();}), - vscode.commands.registerCommand('edk2code.discoverBuildFolders', async ()=>{await cmds.discoverBuildFolders();}), - vscode.commands.registerCommand('edk2code.openConfigurationUi', async ()=>{await cmds.openWpConfigGui();}), - vscode.commands.registerCommand('edk2code.openConfigurationJson', async ()=>{await cmds.openWpConfigJson();}), - vscode.commands.registerCommand('edk2code.rescanIndex', async ()=>{await cmds.rescanIndex();}), - vscode.commands.registerCommand('edk2code.unloadWorkspace', async ()=>{await cmds.unloadWorkspace();}), - vscode.commands.registerCommand('edk2code.help', async ()=>{ - const docUrl = getDocsUrl(); - await vscode.env.openExternal(vscode.Uri.parse(docUrl)); - - }), - vscode.commands.registerCommand('edk2code.openFile', async ()=>{await cmds.openFile();}), - vscode.commands.registerCommand('edk2code.openLib', async()=>{await cmds.openLib();}), - vscode.commands.registerCommand('edk2code.openModule', async ()=>{await cmds.openModule();}), - vscode.commands.registerCommand('edk2code.gotoDefinition', async (fileUri)=>{ await cmds.gotoDefinitionCscope(fileUri);}), - vscode.commands.registerCommand('edk2code.gotoDefinitionInput', ()=>{cmds.gotoDefinitionInput();}), - - vscode.commands.registerCommand('edk2code.gotoInf',async (fileUri)=>{await cmds.gotoInf(fileUri);}), - vscode.commands.registerCommand('edk2code.dscUsage', async (fileUri)=>{await cmds.gotoDscDeclaration(fileUri);}), - vscode.commands.registerCommand('edk2code.dscInclusion', async (fileUri)=>{await cmds.gotoDscInclusion(fileUri);}), - vscode.commands.registerCommand('edk2code.buildEdk2Workspace', async ()=>{await cmds.buildEdk2Workspace();}), - vscode.commands.registerCommand('edk2code.buildFromTree', async (node)=>{await cmds.buildFromTree(node);}), - - // Internal - vscode.commands.registerCommand('edk2code.searchDefinition', ()=>{}), - vscode.commands.registerCommand("edk2code.gotoFile", async (fileUri, selRange)=>{await gotoFile(fileUri,selRange);}), - - vscode.commands.registerCommand('edk2code.driverInfoGoToDefinition', async (symbol: any) => { - if (symbol && symbol.onDefinition) { - const locations = await symbol.onDefinition(symbol.parser); - if (locations) { - const locArray = Array.isArray(locations) ? locations : [locations]; - if (locArray.length > 0) { - const loc = locArray[0]; - const suppressed = gDriverInfoTreeProvider.suppressNextUpdate(); - if (loc.uri && loc.range) { - await gotoFile(loc.uri, loc.range); - } else if (loc.uri) { - await vscode.commands.executeCommand('vscode.open', loc.uri, { preview: suppressed }); - } - if (!suppressed) { - // Double-click: force update - const editor = vscode.window.activeTextEditor; - if (editor) { await gDriverInfoTreeProvider.onEditorChanged(editor); } - } - } - } - } - }), - - vscode.commands.registerCommand('edk2code.driverInfoOpenFile', async (fileUri: vscode.Uri, options?: any) => { - const suppressed = gDriverInfoTreeProvider.suppressNextUpdate(); - const openOptions = suppressed ? { ...options, preview: true } : { ...options, preview: false }; - await vscode.commands.executeCommand('vscode.open', fileUri, openOptions); - if (!suppressed) { - // Double-click: force update - const editor = vscode.window.activeTextEditor; - if (editor) { await gDriverInfoTreeProvider.onEditorChanged(editor); } - } - }), - - vscode.commands.registerCommand('edk2code.driverInfoGotoDsc', async () => { - const infUri = gDriverInfoTreeProvider.currentInfUri; - if (infUri) { - await cmds.gotoDscDeclaration(infUri); - } - }), - // vscode.commands.registerCommand("edk2code.viewWarnings", async ()=>{await gErrorReportAgent.reportErrors();}), - - - // Debug - vscode.commands.registerCommand('edk2code.debugCommand', async ()=>{ - - let doc = getCurrentDocument()!; - let parser = await getParserForDocument(doc); - let content = ""; - for (const symb of parser?.symbolsList!) { - content += `${symb.toString()}\n`; - } - await showVirtualFile(doc.fileName,content); - }), - - - - vscode.commands.registerCommand('edk2code.copyWorkspaceTree', async () => { - const text = await vscode.window.withProgress( - { - location: vscode.ProgressLocation.Notification, - title: 'Serializing workspace tree', - cancellable: false - }, - async progress => { - progress.report({ message: 'Building tree text for the clipboard...' }); - return await edkWorkspaceTreeProvider.serializeTree(); - } - ); - await vscode.env.clipboard.writeText(text); - void vscode.window.showInformationMessage('Workspace tree copied to clipboard.'); - }), - - vscode.commands.registerCommand('edk2code.copyWorkspaceNodePath', async (node: WorkspaceRootItem | IncludeTreeItem | DocumentSymbolItem) => { - if (!('nodePath' in node)) { - return; - } - await vscode.env.clipboard.writeText(node.nodePath); - void vscode.window.showInformationMessage(`Workspace path copied to clipboard`); - }), - - vscode.commands.registerCommand('edk2code.filterWorkspaceSymbols', async () => { - await edkWorkspaceTreeProvider.showFilterPicker(); - }), - - vscode.commands.registerCommand('edk2code.gotoOverwrite', async (node: DocumentSymbolItem) => { - if (node?.overwrittenBy) { - await gotoFile(node.overwrittenBy.uri, node.overwrittenBy.range); - await edkWorkspaceTreeProvider.revealLocation( - node.overwrittenBy.uri, - node.overwrittenBy.range.start, - edkWorkspaceTreeView - ); - } - }), - - vscode.commands.registerCommand('edk2code.refreshWorkspaceConfig', async () => { - await gEdkWorkspaces.loadConfig(); - }), - - vscode.commands.registerCommand('edk2code.selectWorkspaceView', async () => { - const workspaces = gEdkWorkspaces.workspaces; - if (workspaces.length === 0) { - void vscode.window.showInformationMessage('No EDK2 workspaces loaded yet.'); - return; - } - const items = workspaces.map((ws, i) => ({ - label: ws.platformName ?? path.basename(ws.mainDsc.fsPath), - description: vscode.workspace.asRelativePath(ws.mainDsc, false), - index: i - })); - const picked = await vscode.window.showQuickPick(items, { - placeHolder: 'Select workspace to display', - title: 'EDK2: Select Workspace' - }); - if (picked !== undefined) { - edkWorkspaceTreeProvider.selectWorkspace(picked.index); - } - }), - - vscode.commands.registerCommand('edk2code.revealEditorInWorkspaceTree', async () => { - await edkWorkspaceTreeProvider.revealActiveEditor(edkWorkspaceTreeView); - }), - - vscode.commands.registerCommand('edk2code.searchWorkspaceTree', async () => { - await edkWorkspaceTreeProvider.searchTree(edkWorkspaceTreeView); - }), - - vscode.commands.registerCommand('edk2code.clearWorkspaceTreeSearch', () => { - edkWorkspaceTreeProvider.clearSearchFilter(); - }), - - vscode.commands.registerCommand('edk2code.focusEditorInWorkspaceView', async () => { - const editor = vscode.window.activeTextEditor; - if (!editor) { return; } - - const langId = editor.document.languageId; - - // Helper: switch to the workspace that contains the given URI if it's - // not the currently displayed one. Returns false if user cancelled. - async function ensureWorkspaceForUri(uri: vscode.Uri): Promise { - const allWs = gEdkWorkspaces.workspaces; - const currentIdx = edkWorkspaceTreeProvider.activeIndex; - // Already showing the right workspace? - if (currentIdx < allWs.length && isFileInWorkspaceTree(uri, [allWs[currentIdx]])) { - return true; - } - // Search other workspaces - for (let i = 0; i < allWs.length; i++) { - if (i === currentIdx) { continue; } - if (isFileInWorkspaceTree(uri, [allWs[i]])) { - const wsName = allWs[i].platformName ?? path.basename(allWs[i].mainDsc.fsPath); - const answer = await vscode.window.showInformationMessage( - `File not found in the current workspace tree. Switch to "${wsName}"?`, - { modal: false }, - 'Switch' - ); - if (answer !== 'Switch') { return false; } - edkWorkspaceTreeProvider.selectWorkspace(i); - return true; - } - } - return true; - } - - // DSC / DSC-include: reveal directly by cursor position - if (langId === 'edk2_dsc') { - if (!await ensureWorkspaceForUri(editor.document.uri)) { return; } - await edkWorkspaceTreeProvider.revealActiveEditor(edkWorkspaceTreeView); - return; - } - - // INF: first find DSC declaration(s), then reveal that location - if (langId === 'edk2_inf') { - const fileUri = editor.document.uri; - const wps = await gEdkWorkspaces.getWorkspace(fileUri); - - let declarations: InfDsc[] = []; - for (const wp of wps) { - declarations = declarations.concat(await wp.getDscDeclaration(fileUri)); - } - - if (declarations.length === 0) { - void vscode.window.showInformationMessage('This INF file has no DSC declaration in the loaded workspaces.'); - return; - } - - let chosen: InfDsc; - if (declarations.length === 1) { - chosen = declarations[0]; - } else { - const items = declarations.map(d => ({ - label: vscode.workspace.asRelativePath(d.location.uri, false), - description: `line ${d.location.range.start.line + 1}`, - detail: d.text.trim(), - decl: d - })); - const picked = await vscode.window.showQuickPick(items, { - placeHolder: 'Multiple DSC declarations found – select one to reveal', - title: 'EDK2: Focus on workspace view' - }); - if (!picked) { return; } - chosen = picked.decl; - } - - if (!await ensureWorkspaceForUri(chosen.location.uri)) { return; } - await edkWorkspaceTreeProvider.revealLocation( - chosen.location.uri, - chosen.location.range.start, - edkWorkspaceTreeView - ); - } - }), - - vscode.commands.registerCommand('edk2code.compileCFile', async (fileUriOrItem?: vscode.Uri | vscode.TreeItem) => { - let uri: vscode.Uri | undefined; - if (fileUriOrItem instanceof vscode.Uri) { - uri = fileUriOrItem; - } else if (fileUriOrItem && 'resourceUri' in fileUriOrItem && fileUriOrItem.resourceUri) { - uri = fileUriOrItem.resourceUri; - } - await compileCFile(uri); - }), - - vscode.commands.registerCommand('edk2code.startMcpServer', async () => { - const portStr = vscode.workspace.getConfiguration('edk2code').get('mcpServerPort', 3100); - await startMcpServer(portStr); - }), - vscode.commands.registerCommand('edk2code.stopMcpServer', () => { - stopMcpServer(); - }) - ]; - - // We need to concat custom commands, because they are not in the list of commands - // because they are added after the extension is activated - context.subscriptions.push(...commands); - gExtensionContext = context; - edkStatusBar.init(context); - - gConfigAgent.initConfigWatcher(); - - initLanguages(); - gMapFileManager = new MapFilesManager(); - gCompileCommands = new CompileCommands(); - - edkWorkspaceTreeProvider = new WorkspaceTreeProvider(); - edkWorkspaceTreeView = vscode.window.createTreeView('workspaceView', { treeDataProvider: edkWorkspaceTreeProvider, showCollapseAll: true, dragAndDropController: edkWorkspaceTreeProvider }); - - gDriverInfoTreeProvider = new DriverInfoTreeProvider(); - const driverInfoTreeView = vscode.window.createTreeView('driverInfoView', { treeDataProvider: gDriverInfoTreeProvider, showCollapseAll: true }); - gDriverInfoTreeProvider.setTreeView(driverInfoTreeView); - - await gEdkWorkspaces.loadConfig(); - gFileUseWarning = new FileUseWarning(); - - // Start periodic scan for build folders in workspace - cmds.startBuildFolderScan(); - - - - - gCscope = new Cscope(); - gCscopeAgent = new CscopeAgent(); - - if(gConfigAgent.getUseCscope() && gCscope.existCscopeFile()){ - void gCscope.reload().then(()=>{ - if(gConfigAgent.getUseEdkCallHiearchy()){ - gEdk2CallHierarchyProvider = new Edk2CallHierarchyProvider(); - } - }); - } - - - - - // ─── Track whether the active editor belongs to the workspace tree ───────── - async function updateEditorInWorkspaceContext(editor: vscode.TextEditor | undefined): Promise { - const uri = editor?.document.uri; - const langId = editor?.document.languageId; - - const inDscTree = - uri !== undefined && - isFileInWorkspaceTree(uri, gEdkWorkspaces.workspaces); - - const inInfWorkspace = - uri !== undefined && - langId === 'edk2_inf' && - isInfInWorkspaces(uri, gEdkWorkspaces.workspaces); - - void vscode.commands.executeCommand('setContext', 'edk2code.editorFileInWorkspaceTree', inDscTree); - void vscode.commands.executeCommand('setContext', 'edk2code.infFileInWorkspaceTree', inInfWorkspace); - } - context.subscriptions.push( - vscode.window.onDidChangeActiveTextEditor(editor => { void updateEditorInWorkspaceContext(editor); }) - ); - void updateEditorInWorkspaceContext(vscode.window.activeTextEditor); - - void showReleaseNotes(context); - -} - - - - - -// this method is called when your extension is deactivated -export async function deactivate() { - stopMcpServer(); - cmds.stopBuildFolderScan(); -} - - - - - - - - - - diff --git a/src/grayout.ts b/src/grayout.ts deleted file mode 100644 index de08244..0000000 --- a/src/grayout.ts +++ /dev/null @@ -1,192 +0,0 @@ -import * as vscode from 'vscode'; - -import { gDebugLog } from './extension'; - -/** - * Manages grayout decorations for inactive code regions across all documents. - * - * Uses a single shared TextEditorDecorationType and a single set of event - * listeners instead of per-file controllers. This avoids: - * - Creating/disposing decoration types on every tab switch (main perf issue) - * - N event listeners for N files - * - Reference equality checks on TextDocument that silently fail - */ -export class GrayoutManager { - /** Single shared decoration type — created once, reused for all files */ - private decoration: vscode.TextEditorDecorationType; - - /** Map from fsPath -> grayout ranges for that file */ - private rangeMap: Map = new Map(); - - private disposables: vscode.Disposable[] = []; - - constructor() { - this.decoration = vscode.window.createTextEditorDecorationType({ - isWholeLine: true, - light: { opacity: "0.3" }, - dark: { opacity: "0.3" }, - }); - - // Single listener: re-apply decorations when the active editor changes - this.disposables.push( - vscode.window.onDidChangeActiveTextEditor((editor) => { - if (editor) { - this.applyToEditor(editor); - } - }) - ); - - // Handle split editors and editor reuse - this.disposables.push( - vscode.window.onDidChangeVisibleTextEditors((editors) => { - for (const editor of editors) { - this.applyToEditor(editor); - } - }) - ); - } - - /** - * Store grayout ranges for a document and immediately apply decorations - * to all visible editors showing that document. - */ - setRanges(uri: vscode.Uri, ranges: vscode.Range[]) { - gDebugLog.trace(`GrayoutManager.setRanges(): ${uri.fsPath} (${ranges.length} ranges)`); - this.rangeMap.set(uri.fsPath, ranges); - this.applyToUri(uri.fsPath); - } - - /** - * Remove grayout ranges for a document and clear its decorations. - */ - clearRanges(uri: vscode.Uri) { - gDebugLog.trace(`GrayoutManager.clearRanges(): ${uri.fsPath}`); - this.rangeMap.delete(uri.fsPath); - this.applyToUri(uri.fsPath); - } - - /** - * Remove all grayout ranges and clear decorations from all visible editors. - */ - clearAll() { - gDebugLog.trace(`GrayoutManager.clearAll()`); - this.rangeMap.clear(); - // Clear decorations on all visible editors - for (const editor of vscode.window.visibleTextEditors) { - editor.setDecorations(this.decoration, []); - } - } - - /** - * Apply stored decorations to a specific editor. - */ - private applyToEditor(editor: vscode.TextEditor) { - const fsPath = editor.document.uri.fsPath; - const ranges = this.rangeMap.get(fsPath); - if (ranges && ranges.length > 0) { - gDebugLog.trace(`GrayoutManager: Applying ${ranges.length} ranges to ${fsPath}`); - editor.setDecorations(this.decoration, ranges); - } else { - // Clear any stale decorations for files not in the map - editor.setDecorations(this.decoration, []); - } - } - - /** - * Apply decorations to all visible editors showing the given file. - */ - private applyToUri(fsPath: string) { - for (const editor of vscode.window.visibleTextEditors) { - if (editor.document.uri.fsPath === fsPath) { - this.applyToEditor(editor); - } - } - } - - dispose() { - this.decoration.dispose(); - for (const d of this.disposables) { - d.dispose(); - } - this.disposables = []; - this.rangeMap.clear(); - } -} - -/** - * @deprecated Use GrayoutManager instead. Kept temporarily for backward compatibility. - */ -export class GrayoutController { - decoration:vscode.TextEditorDecorationType|undefined; - - document:vscode.TextDocument; - range:vscode.Range[]; - changeEvent:vscode.Disposable; - - public constructor(document:vscode.TextDocument, range:vscode.Range[]) { - - this.document = document; - - this.range = range; - this.changeEvent = vscode.window.onDidChangeActiveTextEditor(()=>{ - if(vscode.window.activeTextEditor?.document.uri.fsPath === this.document.uri.fsPath){ - this.doGrayOut(); - } - }, this); - - } - - - grayoutRange(unusdedRanges:vscode.Range[]) { - gDebugLog.trace("grayoutRange()"); - let activeEditor = vscode.window.activeTextEditor; - - if(!activeEditor){return;} - if(activeEditor.document.uri.fsPath !== this.document.uri.fsPath){return;} - - gDebugLog.trace(`Unused Ranges: ${JSON.stringify(unusdedRanges)}`); - - this.disposeDecoration(); - - let decoration = vscode.window.createTextEditorDecorationType({ - isWholeLine: true, - light: { - opacity: "0.3", - }, - dark: { - opacity: "0.3", - } - }); - - this.decoration = decoration; - - const blockDecorationOptions: vscode.DecorationOptions[] = []; - for (const targetRange of unusdedRanges) { - const decoration = { range: targetRange}; - blockDecorationOptions.push(decoration); - } - activeEditor?.setDecorations(decoration, blockDecorationOptions); - - } - - - - dispose(){ - this.disposeDecoration(); - this.changeEvent?.dispose(); - } - - disposeDecoration(){ - if(this.decoration){ - this.decoration.dispose(); - } - } - - doGrayOut(){ - if (vscode.window.visibleTextEditors.some(editor => editor.document.uri.fsPath === this.document.uri.fsPath)) { - gDebugLog.info(`doGrayOut(): ${this.document.uri.fsPath}`); - this.grayoutRange(this.range); - } - } - -} \ No newline at end of file diff --git a/src/index/definitions.ts b/src/index/definitions.ts deleted file mode 100644 index 5f39a90..0000000 --- a/src/index/definitions.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { REGEX_VAR_USAGE } from "../edkParser/commonParser"; -import { gConfigAgent, gDebugLog } from "../extension"; -import * as vscode from 'vscode'; -import { split } from "../utils"; - -export const UNDEFINED_VARIABLE = "???"; - - -export interface EdkDefinition { - name:string; - value:string - location:vscode.Location|undefined; -} - -export class WorkspaceDefinitions { - defines:Map; - - - private static instance: WorkspaceDefinitions; - - public static getInstance(): WorkspaceDefinitions { - if (!WorkspaceDefinitions.instance) { - WorkspaceDefinitions.instance = new WorkspaceDefinitions(); - } - return WorkspaceDefinitions.instance; - } - - resetDefines(){ - let buildDefines = new Map(gConfigAgent.getBuildDefines()); - this.defines = new Map(); - // Clean empty definitions - for (const [key,value] of buildDefines.entries()) { - if(value.length > 0){ - this.defines.set(key, {name: key, value:value, location:undefined}); - } - } - - } - - getDefinitions(){ - return this.defines; - } - - getDefinition(key:string){ - let val = this.defines.get(key); - if(val){ - return val.value; - } - return undefined; - } - - getDefinitionLocation(key:string){ - let val = this.defines.get(key); - if(val){ - return val.location; - } - return undefined; - } - - isBoolean(value:string){ - value = value.toLowerCase(); - return value === "true" || value === "false"; - } - - setDefinition(key:string, value:string, location:vscode.Location|undefined){ - - // Expand any existing definitions referenced in the value - value = this.replaceDefines(value); - - gDebugLog.trace(`setDefinition: ${key} = ${value}`); - this.defines.set(key, {name: key, value:value, location:location}); - } - - constructor() { - this.defines = new Map(); - } - - isDefined(text:string){ - return this.defines.has(text); - } - - replaceDefines(text: string) { - let replaced = false; - let maxIterations = 10; - do { - - maxIterations --; - - if(maxIterations <= 0){ - gDebugLog.error(`Max iterations reached: ${text}`); - return text; - } - - replaced = false; - for (const [key,value] of this.defines.entries()) { - if(text.includes(`$(${key})`)){ - replaced = true; - let replacement; - if(value.value.toLowerCase() === "true"){ - replacement = "TRUE"; - }else if(value.value.toLowerCase() === "false"){ - replacement = "FALSE"; - }else{ - replacement = value.value; - } - - - text = text.replaceAll(`$(${key})`, replacement); - } - } - - }while(replaced === true); - // remove undefined variable - // text = text.replaceAll(REGEX_VAR_USAGE, UNDEFINED_VARIABLE); - return text; - } -} \ No newline at end of file diff --git a/src/index/edkWorkspace.ts b/src/index/edkWorkspace.ts deleted file mode 100644 index 301e6e3..0000000 --- a/src/index/edkWorkspace.ts +++ /dev/null @@ -1,1495 +0,0 @@ - -import * as vscode from 'vscode'; -import { edkWorkspaceTreeProvider, edkWorkspaceTreeView, gCompileCommands, gConfigAgent, gDebugLog, gMapFileManager, gPathFind, gWorkspacePath } from '../extension'; -import { GrayoutManager } from '../grayout'; -import { createRange, openTextDocument, pathCompare, split } from '../utils'; -import { REGEX_DEFINE, REGEX_DSC_SECTION, REGEX_EQUAL, REGEX_INCLUDE as REGEX_INCLUDE, REGEX_LIBRARY_PATH, REGEX_MODULE_PATH, REGEX_PCD_LINE, REGEX_VAR_USAGE } from "../edkParser/commonParser"; -import { UNDEFINED_VARIABLE, WorkspaceDefinitions } from "./definitions"; -import * as fs from 'fs'; -import path = require('path'); -import { getParser } from '../edkParser/parserFactory'; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import { EdkSymbolInfLibrary } from '../symbols/infSymbols'; -import { DiagnosticManager, EdkDiagnosticCodes } from '../diagnostics'; -import { PathFind } from '../pathfind'; -import { OPERATORS } from './operations'; -import * as edkStatusBar from '../statusBar'; -import { debuglog } from 'util'; - - -const dscSectionTypes = ['defines','packages','buildoptions','skuids','libraryclasses','components','userextensions','defaultstores','pcdsfeatureflag','pcdsfixedatbuild','pcdspatchableinmodule','pcdsdynamicdefault','pcdsdynamichii','pcdsdynamicvpd','pcdsdynamicexdefault','pcdsdynamicexhii','pcdsdynamicexvpd']; - -// EDK2 built-in macros that should not trigger undefined variable warnings -const EDK2_BUILTIN_MACROS = new Set([ - "WORKSPACE", "EDK_SOURCE", "EFI_SOURCE", "TARGET", "TOOL_CHAIN_TAG", - "ARCH", "MODULE_NAME", "OUTPUT_DIRECTORY", "BUILD_NUMBER", "INF_VERSION", - "NAMED_GUID", "INF_OUTPUT" -]); - -type ConditionBlock = { - active: boolean; // Whether the block is active or not - satisfied: boolean; // Whether the condition has been satisfied - }; - -type ConditonOpenBlock = { - uri:vscode.Uri; - lineNo:number; -}; - -export interface Pcd { - name:string; - value:string - position:vscode.Location -} - -export interface IncludeNode { - /** Location of the !include directive in the parent file */ - location: vscode.Location; - /** Resolved URI of the included file */ - uri: vscode.Uri; - /** Nested includes found inside the included file */ - children: IncludeNode[]; -} - -export class SectionProperties{ - properties: SectionProperty[] = []; - constructor(){ - - } - - - - addProperty(sectionType:string, arch:string, moduleType:string){ - let property = new SectionProperty(sectionType, arch, moduleType); - this.properties.push(property); - } - - compareArch(other:SectionProperties){ - for (const thisProperty of this.properties) { - for (const otherProperty of other.properties) { - if(otherProperty.arch === thisProperty.arch){ - return true; - } - } - } - return false; - } - - compareArchStr(arch:string){ - arch = arch.toLowerCase(); - for (const thisProperty of this.properties) { - if(arch === thisProperty.arch){ - return true; - } - } - return false; - } - - compareLibSectionType(other:SectionProperties){ - for (const thisProperty of this.properties) { - for (const otherProperty of other.properties) { - if(otherProperty.sectionType === thisProperty.sectionType){ - return true; - } - } - } - return false; - } - - compareLibSectionTypeStr(sectionType:string){ - sectionType = sectionType.toLowerCase(); - for (const thisProperty of this.properties) { - if(sectionType === thisProperty.sectionType){ - return true; - } - } - return false; - } - - compareModuleType(other:SectionProperties){ - for (const thisProperty of this.properties) { - for (const otherProperty of other.properties) { - if(otherProperty.moduleType === thisProperty.moduleType){ - return true; - } - } - } - return false; - } - - compareModuleTypeStr(moduleType:string){ - moduleType = moduleType.toLowerCase(); - for (const thisProperty of this.properties) { - if(moduleType === thisProperty.moduleType){ - return true; - } - } - return false; - } - - toString(){ - return this.properties.map(x=>x.toString()).join(","); - } - -} - -export class SectionProperty{ - sectionType:string; - arch:string; - moduleType:string; - - constructor(sectionType:string, arch:string, moduleType:string){ - this.sectionType = sectionType.toLocaleLowerCase(); - this.arch = arch.toLocaleLowerCase(); - this.moduleType = moduleType.toLocaleLowerCase(); - } - -} - -export class InfDsc{ - path: string; - location:vscode.Location; - sectionProperties: SectionProperties; - text:string; - parent: string|undefined; - constructor(filePath:string, location:vscode.Location, parent:string, line:string){ - this.path = filePath.replaceAll("\\",path.sep).replaceAll("/",path.sep); - this.location = location; - this.sectionProperties = new SectionProperties(); - this.text = line; - - if(parent.match(/\.inf$/gi)){ - // Parent its a file - this.parent = parent.replaceAll("\\",path.sep).replaceAll("/",path.sep);; - }else{ - // Parent its a section - this.parent = undefined; - let props = parent.split(","); - for (const p of props) { - let [sectionType,arch,moduleType] = split(p.toLowerCase(),".",3,"common"); - this.sectionProperties.addProperty(sectionType, arch, moduleType); - } - } - - } - - toString(): string { - return `${this.path}:${this.location.range.start.line} - ${JSON.stringify(this.sectionProperties)} }`; - } - - - - - /** - * Retrieves a comma-separated string of module types from the properties. - * - * @returns {string} A comma-separated string of module types. - * - */ - getModuleTypeStr(){ - return this.sectionProperties.properties.map(x=>x.moduleType).join(","); - } -} - - - - -export class EdkWorkspaces { - - private static instance: EdkWorkspaces; - private _workspaces: EdkWorkspace[] = []; - public get workspaces(): EdkWorkspace[] { - return this._workspaces; - } - public set workspaces(value: EdkWorkspace[]) { - this._workspaces = value; - } - - isConfigured(){ - if(this.workspaces.length > 0){ - return true; - } - return false; - } - - public static getInstance() { - if (!EdkWorkspaces.instance) { - EdkWorkspaces.instance = new EdkWorkspaces(); - } - return EdkWorkspaces.instance; - } - - constructor() { - - } - - async getDefinition(uri: vscode.Uri, word: string) { - for (const workspace of this.workspaces) { - let isInUse = await workspace.isFileInUse(uri); - if(isInUse === true){ - return workspace.getDefinitions().get(word); - } - } - return undefined; - } - - async replaceDefines(uri: vscode.Uri, text: string) { - for (const workspace of this.workspaces) { - let isInUse = await workspace.isFileInUse(uri); - if(isInUse === true){ - return workspace.replaceDefine(text); - } - } - return text; - } - - async getLib(location:vscode.Location){ - let libs:InfDsc[] = []; - for (const workspace of this.workspaces) { - let result = await workspace.getLib(location); - if(result){ - libs.push(result); - } - } - return libs; - } - - - -/** - * Asynchronously retrieves a list of workspaces that are using the specified file. - * - * @param uri - The URI of the file to check for usage within the workspaces. - * @returns A promise that resolves to an array of workspaces that are using the specified file. - * - */ -async getWorkspace(uri: vscode.Uri): Promise { - let wps = []; - for (const workspace of this.workspaces) { - let result = await workspace.isFileInUse(uri); - if (result === true) { - wps.push(workspace); - } - } - return wps; -} - - - async isFileInUse(uri: vscode.Uri) { - let isUndefined = true; - for (const workspace of this.workspaces) { - let result = await workspace.isFileInUse(uri); - if(result === true){ - return true; - } - if(result === false){ - isUndefined = false; - continue; - } - } - if(isUndefined){return undefined;} - return false; - } - - async loadConfig() { - this.workspaces = []; - gDebugLog.trace("Loading Configuration"); - await vscode.commands.executeCommand('setContext', 'edk2code.parseComplete', false); - await vscode.commands.executeCommand('setContext', 'edk2code.isLoading', true); - - // If the previous workspace processing did not complete (e.g. - // after a clear), build a temporary T-tree so PathFind can - // resolve files without relying on the empty packagePaths. - await gConfigAgent.buildFileIndexIfNeeded(); - - let dscPaths = gConfigAgent.getBuildDscPaths(); - gDebugLog.trace(`dscPaths = ${dscPaths}`); - for (const dscPath of dscPaths) { - let dscDocument = await openTextDocument(vscode.Uri.file(path.join(gWorkspacePath, dscPath))); - let edkWorkspace = new EdkWorkspace(dscDocument); - await edkWorkspace.proccessWorkspace(); - this.workspaces.push(edkWorkspace); - gDebugLog.info(`Workspace loaded: ${dscDocument.fileName}`); - } - gMapFileManager.load(); - gCompileCommands.load(); - // Workspace processing is complete – mark flag and dispose - // of the temporary T-tree so PathFind reverts to findFiles. - gConfigAgent.setWorkspaceProcessComplete(); - await vscode.commands.executeCommand('setContext', 'edk2code.parseComplete', true); - await vscode.commands.executeCommand('setContext', 'edk2code.isLoading', false); - } -} - - -export class EdkWorkspace { - - id:number = 0; - mainDsc: vscode.Uri; - platformName: string | undefined = undefined; - flashDefinitionDocument: vscode.TextDocument | undefined = undefined; - - conditionStack: ConditionBlock[] = []; - result: boolean[] = []; - conditionOpen:ConditonOpenBlock[] = []; - - private workInProgress: boolean = false; - private processComplete: boolean = false; - - private conditionalStack: boolean[] = []; - private sectionsStack: string[] = []; - private parsedDocuments: Map = new Map(); - - - // Elements - private defines: WorkspaceDefinitions = new WorkspaceDefinitions(); - private pcdDefinitions: Map> = new Map(); - - definesFdf: WorkspaceDefinitions = new WorkspaceDefinitions(); - - private libraryTypeTrack = new Map(); - - private _filesLibraries: InfDsc[] = []; - public get filesLibraries(): InfDsc[] { - return this._filesLibraries; - } - public set filesLibraries(value: InfDsc[]) { - this._filesLibraries = value; - } - private _filesModules: InfDsc[] = []; - public get filesModules(): InfDsc[] { - return this._filesModules; - } - public set filesModules(value: InfDsc[]) { - this._filesModules = value; - } - private _filesDsc: Set = new Set(); - private _filesFdf: Set = new Set(); - - public get filesDsc(): Set { - return this._filesDsc; - } - public set filesDsc(value: Set) { - this._filesDsc = value; - } - public get filesFdf(): Set { - return this._filesFdf; - } - public set filesFdf(value: Set) { - this._filesFdf = value; - } - - private _grayoutManager: GrayoutManager = new GrayoutManager(); - - private _includeTree: IncludeNode[] = []; - public get includeTree(): IncludeNode[] { - return this._includeTree; - } - - public updateGrayoutRange(document: vscode.TextDocument, range: vscode.Range[]){ - this._grayoutManager.setRanges(document.uri, range); - } - - public dscList(){ - return Array.from(this.filesDsc).map(x=>x.uri.fsPath); - } - - public fdfList(){ - return Array.from(this.filesFdf).map(x=>x.uri.fsPath); - } - - public getFilesList(){ - let fileList = [...this.dscList(),...this.fdfList(),...this.filesModules.map(x=>x.path),...this.filesLibraries.map(x=>x.path)]; - return fileList; - } - - - constructor(document: vscode.TextDocument) { - this.mainDsc = document.uri; - // generate random number - this.id = Math.floor(Math.random() * 100000000000000); - } - - - - - async proccessWorkspace() { - return vscode.window.withProgress( - { location: { viewId: 'workspaceView' } }, - async () => { - return this._doProccessWorkspace(); - } - ); - } - - private async _doProccessWorkspace() { - try{ - if(this.platformName !== undefined){ - edkStatusBar.pushText(`Parsing ${this.platformName}`); - }else{ - edkStatusBar.pushText(`Loading ${this.mainDsc.fsPath}`); - } - - edkStatusBar.setWorking(); - if (this.workInProgress) { - return false; - } - // reset conditional stack - this.workInProgress = true; - gDebugLog.trace(`Start finding defines in ${this.mainDsc.fsPath}`); - this.conditionalStack = []; - - this.defines.resetDefines(); - this.definesFdf.resetDefines(); - - this.filesLibraries = []; - this.filesModules = []; - this.filesDsc = new Set(); - this._grayoutManager.clearAll(); - this.libraryTypeTrack = new Map(); - - - this.conditionStack = []; - this.result = []; - this.conditionOpen = []; - this._includeTree = []; - - - - - - - this.parsedDocuments = new Map(); - let mainDscDocument = await vscode.workspace.openTextDocument(this.mainDsc); - await this._processDocument(mainDscDocument, "DSC"); - for (const conditionOpen of this.conditionOpen) { - DiagnosticManager.error(conditionOpen.uri,conditionOpen.lineNo,EdkDiagnosticCodes.conditionalMissform, "Condition block not closed"); - } - this.workInProgress = false; - gDebugLog.trace("Finding done."); - - // Populate workspace definitions - this.platformName = this.defines.getDefinition("PLATFORM_NAME") || undefined; - let flashDefinitionString = this.defines.getDefinition("FLASH_DEFINITION") || undefined; - if (flashDefinitionString) { - let flashDefinitionPath = await gPathFind.findPath(flashDefinitionString, path.dirname(this.mainDsc.fsPath)); - if(flashDefinitionPath.length>0){ - this.flashDefinitionDocument = await openTextDocument(flashDefinitionPath[0].uri); - } - } - - await this.findDefinesFdf(); - - this.processComplete = true; - edkWorkspaceTreeProvider.refresh(); - return true; - }finally{ - edkStatusBar.popText(); - edkStatusBar.clearWorking(); - } - - } - - async getInfReference(uri: vscode.Uri) { - const workspaceBase = vscode.Uri.file(gWorkspacePath); - let fileName = path.basename(uri.fsPath); - let folder = vscode.Uri.file(path.dirname(uri.fsPath)); - - let returns:vscode.Location[] = []; - let found = false; - while(folder.fsPath !== workspaceBase.fsPath){ - let files = fs.readdirSync(folder.fsPath); - for (const file of files) { - if (file.match(/\.inf$/gi)) { - // open textdocument from file - let filePath = path.join(folder.fsPath, file); - let infDocument = await openTextDocument(vscode.Uri.file(filePath)); - - if(!await this.isFileInUse(infDocument.uri)){continue;} - let lineIndex = 0; - for(const line of infDocument.getText().split(/\r?\n/g)){ - let m = line.match(new RegExp(`\\b${fileName}\\b`,"gim")); - if(m){ - found = true; - returns.push(new vscode.Location(infDocument.uri, createRange(lineIndex,lineIndex,0))); - } - lineIndex++; - } - } - if(found){ - return returns; - } - } - folder = vscode.Uri.file(path.dirname(folder.fsPath)); - } - - return returns; - } - - getDefinitions() { - return this.defines.getDefinitions(); - } - - getDefinition(key:string){ - return this.defines.getDefinition(key); - } - - getDefinitionLocation(key:string){ - return this.defines.getDefinitionLocation(key); - } - - replaceDefine(text: string) { - return this.defines.replaceDefines(text); - } - - - getPcds(namespace: any) { - return this.pcdDefinitions.get(namespace); - } - - getAllPcds() { - return this.pcdDefinitions; - } - - - private stripComment(line: string): string { - if (!line.includes("#")) { - return line.trim(); - } - - const result: string[] = []; - let insideQuotes = false; - let quoteChar: string | null = null; - let escaped = false; - - for (const char of line) { - if ((char === '"' || char === "'") && !escaped) { - if (!insideQuotes) { - insideQuotes = true; - quoteChar = char; - } else if (char === quoteChar) { - insideQuotes = false; - quoteChar = null; - } - } else if (char === "#" && !insideQuotes) { - break; - } else if (char === "\\" && !escaped) { - escaped = true; - } else { - escaped = false; - } - - result.push(char); - } - - return result.join("").trimEnd(); - } - - - private async _processDocument(document: vscode.TextDocument, type: 'DSC' | 'FDF', parentIncludeNode?: IncludeNode) { - - DiagnosticManager.clearProblems(document.uri); - gDebugLog.trace(`_process${type}: ${document.fileName}`); - - if (this.isDocumentInIndex(document)) { - gDebugLog.trace(`_process${type}: ${document.fileName} already in inactiveLines`); - return; - } - - let doucumentGrayoutRange = []; - this.parsedDocuments.set(document.uri.fsPath, []); - if (type === 'DSC') { - this.filesDsc.add(document); - } else { - this.filesFdf.add(document); - } - - let text = document.getText().split(/\r?\n/); - let lineIndex = -1; - let isRangeActive = false; - let unuseRangeStart = 0; - - gDebugLog.trace(`# Parsing ${type} Document: ${document.uri.fsPath}`); - for (let line of text) { - lineIndex++; - - gDebugLog.trace(`\t\t${lineIndex}: ${line}`); - line = this.stripComment(line); - let originalLine = line; - - if (line.length === 0){continue;} - - // PCDs - if (line.match(REGEX_PCD_LINE)) { - let [fullPcd, pcdValue] = split(line, "|", 2); - pcdValue = pcdValue.split("|")[0].trim(); - if (pcdValue.startsWith('L"')) { - pcdValue = pcdValue.slice(1); - } - let [pcdNamespace, pcdName] = split(fullPcd, ".", 2); - if (!this.pcdDefinitions.has(pcdNamespace)) { - this.pcdDefinitions.set(pcdNamespace, new Map()); - } - this.pcdDefinitions.get(pcdNamespace)?.set( - pcdName, - { - name: pcdName, - value: pcdValue, - position: new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)) - } - ); - } - - line = this.defines.replaceDefines(line); - line = this.replacePcds(line); - let isInActiveCode = this.processConditional(line, lineIndex, document.uri); - - if (!isInActiveCode) { - if (!isRangeActive) { - isRangeActive = true; - unuseRangeStart = lineIndex; - } - continue; - } - - if(line.startsWith("!error ")){ - DiagnosticManager.error(document.uri, lineIndex, EdkDiagnosticCodes.errorMessage, line.replace("!error ","")); - } - - if (isRangeActive) { - isRangeActive = false; - let lineIndexEnd = lineIndex - 1; - gDebugLog.debug(`New grayout ${document.fileName} -> unuseRangeStart: ${unuseRangeStart} lineIndexEnd: ${lineIndexEnd}`); - doucumentGrayoutRange.push(new vscode.Range(new vscode.Position(unuseRangeStart, 0), new vscode.Position(lineIndexEnd, 0))); - } - - if (type === 'DSC') { - // Sections - let match = line.match(REGEX_DSC_SECTION); - if (match) { - const sectionType = match[0].split(".")[0]; - if (!dscSectionTypes.includes(sectionType.toLowerCase())) { - DiagnosticManager.warning(document.uri, lineIndex, EdkDiagnosticCodes.unknownSectionType, sectionType); - } - this.sectionsStack = [match[0]]; - continue; - } - } - - // Defines - if (line.match(REGEX_DEFINE) || - (this.sectionsStack.length > 0 && - this.sectionsStack[this.sectionsStack.length - 1].toLowerCase() === "defines" && - line.match(REGEX_EQUAL))) { - let key = line.replace(/define/gi, "").trim(); - key = split(key, "=", 2)[0].trim(); - let value = split(line, "=", 2)[1].trim(); - let originalValue = split(originalLine, "=", 2)[1].trim(); - - if (value.includes(`$(${key})`) || originalValue.includes(`$(${key})`)) { - gDebugLog.trace(`Circular define: ${key}: ${value}`); - } else { - // Warn if DEFINE is being redefined without referencing itself - let defines = type === 'DSC' ? this.defines : this.definesFdf; - if (defines.isDefined(key)) { - let previousLocation = defines.getDefinitionLocation(key); - let relatedInfo: vscode.DiagnosticRelatedInformation[] | undefined; - if (previousLocation) { - relatedInfo = [ - new vscode.DiagnosticRelatedInformation( - previousLocation, - `Previous definition of '${key}'` - ) - ]; - } - DiagnosticManager.warning( - document.uri, - lineIndex, - EdkDiagnosticCodes.duplicateDefine, - `'${key}' is redefined without referencing its previous value. Use $(${key}) to extend it.`, - [], - relatedInfo - ); - } - - if (type === 'DSC') { - this.defines.setDefinition(key, value, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0))); - } else { - this.definesFdf.setDefinition(key, value, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0))); - } - - // Warn about undefined variables directly referenced in the raw value - - let unresolvedVars = originalValue.match(REGEX_VAR_USAGE); - if (unresolvedVars) { - let defines = type === 'DSC' ? this.defines : this.definesFdf; - for (const unresolved of new Set(unresolvedVars)) { - let varName = unresolved.replace(/\$\(\s*/, '').replace(/\s*\)/, ''); - if (!defines.isDefined(varName) && !EDK2_BUILTIN_MACROS.has(varName.toUpperCase())) { - DiagnosticManager.warning(document.uri, lineIndex, EdkDiagnosticCodes.undefinedVariable, `${unresolved}`); - } - } - } - } - continue; - } - - // Includes - if (line.match(REGEX_INCLUDE)) { - let value = line.replace(/!include/gi, "").trim(); - let location = await gPathFind.findPath(value, document.uri.fsPath); - if (location.length > 0) { - gDebugLog.trace(`START Including: ${location[0].uri.fsPath}`); - const includeNode: IncludeNode = { - location: new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)), - uri: location[0].uri, - children: [] - }; - if (parentIncludeNode) { - parentIncludeNode.children.push(includeNode); - } else { - this._includeTree.push(includeNode); - } - let includedDocument = await openTextDocument(location[0].uri); - if (type === 'DSC') { - await this._processDocument(includedDocument, 'DSC', includeNode); - } else { - this.filesFdf.add(includedDocument); - await this._processDocument(includedDocument, 'FDF', includeNode); - } - gDebugLog.trace(`END Including: ${location[0].uri.fsPath}`); - } - continue; - } - - if (type === 'DSC') { - - // Libraries - let match = line.match(REGEX_LIBRARY_PATH); - if (match) { - let filePath = match[0].trim(); - let results = await gPathFind.findPath(filePath, document.uri.fsPath); - if (results.length === 0) { - DiagnosticManager.error(document.uri, lineIndex, EdkDiagnosticCodes.missingPath, filePath); - } - let newLibDefinition = new InfDsc(filePath, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)), this.sectionsStack[this.sectionsStack.length - 1], line); - const libName = newLibDefinition.text.split("|")[0].trim(); - const libNameTag = libName + " - " + newLibDefinition.getModuleTypeStr(); - if (this.libraryTypeTrack.has(libNameTag) && (libName.toLocaleLowerCase() !== "null") && newLibDefinition.parent === undefined) { - if (this.sectionsStack[this.sectionsStack.length - 1].toLowerCase().endsWith(".inf")) { - continue; - } - let previousLibDefinition = this.libraryTypeTrack.get(libNameTag)!; - DiagnosticManager.warning(previousLibDefinition.location.uri, previousLibDefinition.location.range.start.line, - EdkDiagnosticCodes.duplicateStatement, - `Library overwritten: ${libName}`, - [vscode.DiagnosticTag.Unnecessary], - [new vscode.DiagnosticRelatedInformation(newLibDefinition.location, "New definition")]); - const index = this.filesLibraries.indexOf(previousLibDefinition); - if (index > -1) { - this.filesLibraries[index] = newLibDefinition; - } - } else { - this.filesLibraries.push(newLibDefinition); - } - this.libraryTypeTrack.set(libNameTag, newLibDefinition); - continue; - } - - // Modules - match = line.match(REGEX_MODULE_PATH); - if (match) { - let filePath = match[0].trim(); - let results = await gPathFind.findPath(filePath, document.uri.fsPath); - if (results.length === 0) { - DiagnosticManager.error(document.uri, lineIndex, EdkDiagnosticCodes.missingPath, filePath); - } - let inf = new InfDsc(filePath, new vscode.Location(document.uri, new vscode.Position(lineIndex, 0)), this.sectionsStack[0], line); - if (filePath.toLowerCase().endsWith(".inf")) { - if (this.sectionsStack[this.sectionsStack.length - 1].toLowerCase().endsWith(".inf")) { - this.sectionsStack.pop(); - } - } - this.sectionsStack.push(filePath); - this.filesModules.push(inf); - continue; - } - } - } - - if (isRangeActive) { - isRangeActive = false; - let lineIndexEnd = lineIndex - 1; - gDebugLog.debug(`New grayout ${document.fileName} -> unuseRangeStart: ${unuseRangeStart} lineIndexEnd: ${lineIndexEnd}`); - doucumentGrayoutRange.push(new vscode.Range(new vscode.Position(unuseRangeStart, 0), new vscode.Position(lineIndexEnd, 0))); - } - - this.parsedDocuments.set(document.uri.fsPath, doucumentGrayoutRange); - this.updateGrayoutRange(document, doucumentGrayoutRange); - - } - - private getLangId(uri:vscode.Uri){ - if(uri.fsPath.toLowerCase().endsWith(".dsc") || uri.fsPath.toLowerCase().endsWith(".dsc.inc")){ - return "edk2_dsc"; - } - if(uri.fsPath.toLowerCase().endsWith(".fdf") || uri.fsPath.toLowerCase().endsWith(".fdf.inc")){ - return "edk2_fdf"; - } - - if(uri.fsPath.toLowerCase().endsWith(".dec") || uri.fsPath.toLowerCase().endsWith(".dec.inc")){ - return "edk2_dec"; - } - if(uri.fsPath.toLowerCase().endsWith(".c") || uri.fsPath.toLowerCase().endsWith(".h")){ - return "c"; - } - if(uri.fsPath.toLowerCase().endsWith(".inf")){ - return "edk2_inf"; - } - - return undefined; - } - - replacePcds(line:string){ - // replace PCDS - let pcds = line.match(/(?:[\w\d\[\]]+\.)+[\w\d\[\]]+/gi); - if(pcds){ - for (const pcd of pcds) { - let [namespace,name] = split(pcd,".",2); - let defPcd = this.pcdDefinitions.get(namespace); - if(defPcd){ - let foundPcd = defPcd.get(name); - if(foundPcd){ - line = line.replaceAll(pcd,foundPcd.value); - } - } - - } - } - return line; - } - - - async isFileInUse(uri: vscode.Uri) { - - if (this.processComplete) { - - switch (this.getLangId(uri)) { - case "edk2_dsc": - case "edk2_fdf": - // fdf files can be included in dsc files - for (const dsc of this.filesDsc) { - - if(uri.fsPath === dsc.fileName) { - return true; - } - } - - - - for (const fdf of this.filesFdf) { - if(uri.fsPath === fdf.fileName){ - return true; - } - } - return false; - case "edk2_dec": - break; - case "edk2_inf": - for (const mods of this.filesModules) { - if(uri.fsPath.includes(mods.path)){ - return true; - } - } - for (const lib of this.filesLibraries) { - if(uri.fsPath.includes(lib.path)){ - return true; - } - }`` - return false; - - case "c": - let relativeInf:string[] = []; - let cDirName = path.dirname(uri.fsPath); - for (const mods of this.filesModules) { - let modDir = path.dirname(mods.path); - if(cDirName.includes(modDir)){ - relativeInf.push(mods.path); - } - } - for (const lib of this.filesLibraries) { - let libDir = path.dirname(lib.path); - if(cDirName.includes(libDir)){ - relativeInf.push(lib.path); - } - } - for (const inf of relativeInf) { - let infLocation = await gPathFind.findPath(inf); - - if (infLocation.length === 0){continue;} - - let parser = await getParser(infLocation[0].uri); - if (parser) { - let sources = parser.getSymbolsType(Edk2SymbolType.infSource); - for (const source of sources) { - let sourceLocation = await gPathFind.findPath(await source.getValue(), path.dirname(infLocation[0].uri.fsPath)); - if(sourceLocation[0].uri.fsPath === uri.fsPath){ - return true; - } - } - } - } - return false; - } - } - return undefined; - } - - async getIncludeReference(uri:vscode.Uri){ - let includePathsFiles:string[] = []; - let retLocations:vscode.Location[] = []; - for (const p of this.filesDsc) { - includePathsFiles.push(p.fileName); - } - for (const p of this.filesFdf) { - includePathsFiles.push(p.fileName); - } - for (const includedFile of includePathsFiles) { - let filePath = await gPathFind.findPath(includedFile); - if(filePath.length){ - let document = await openTextDocument(filePath[0].uri); - let lineIndex = -1; - for (let line of document.getText().split(/\r?\n/)) { - lineIndex ++; - if(line.match(/\!include\s/gi)){ - line = this.defines.replaceDefines(line); - let value = line.replace(/!include/gi, "").trim(); - let location = await gPathFind.findPath(value, path.dirname(document.uri.fsPath)); - if (!location.length){continue;} - gDebugLog.trace(`Looking include: ${location[0].uri.fsPath}`); - if(location[0].uri.fsPath === uri.fsPath){ - gDebugLog.trace(`Include found: ${location[0].uri.fsPath} in ${document.uri.fsPath} line ${lineIndex}`); - retLocations.push(new vscode.Location(document.uri, createRange(lineIndex,lineIndex,0))); - } - } - } - } - } - return retLocations; - } - - isDocumentInIndex(document: vscode.TextDocument): boolean { - return this.parsedDocuments.has(document.uri.fsPath); - } - - getGrayoutRange(document: vscode.TextDocument): vscode.Range[] { - return this.parsedDocuments.get(document.uri.fsPath) || []; - } - - getGrayoutRangeByUri(uri: vscode.Uri): vscode.Range[] { - return this.parsedDocuments.get(uri.fsPath) || []; - } - - - - async findDefinesFdf() { - if (this.workInProgress) { - return false; - } - // reset conditional stack - this.workInProgress = true; - gDebugLog.trace(`Start finding defines fdf`); - this.conditionalStack = []; - - if (this.flashDefinitionDocument) { - if (!this.isDocumentInIndex(this.flashDefinitionDocument)) { - this.filesFdf = new Set(); - await this._processDocument(this.flashDefinitionDocument,"FDF"); - } - } - this.workInProgress = false; - gDebugLog.trace("Finding fdf done."); - return true; - } - - - - - async fdfPostProcces(document: vscode.TextDocument) { - // preprocess fdf files - if (this.processComplete) { - let isComplete = await this.findDefinesFdf(); - if (isComplete) { - // check if document is in index documents - if (this.isDocumentInIndex(document)) { - let grayoutRange = this.getGrayoutRange(document); - this._grayoutManager.setRanges(document.uri, grayoutRange); - return; - } - } - } - } - - - private processConditional(inputText: string, lineIndex:number, documentUri:vscode.Uri):boolean { - let conditionStr = inputText.replaceAll(REGEX_VAR_USAGE, `"${UNDEFINED_VARIABLE}"`); - - // text = text.replaceAll(UNDEFINED_VARIABLE, '"???"'); - - let tokens = []; - if (conditionStr.includes('"')) { - tokens = conditionStr.split('"'); - if(tokens.length%2 !== 1){ // check if there is an open string - DiagnosticManager.error(documentUri,lineIndex,EdkDiagnosticCodes.syntaxStatement, inputText); - return true; - } - tokens = [...tokens[0].trim().split(" "), ...[tokens[1].trim()], ...tokens[2].trim().split(" ")]; - } else { - tokens = conditionStr.trim().split(" "); - } - tokens = tokens.filter(x => { return x.length > 0; }); - if (tokens.length === 0) { - return this.result[this.result.length - 1]; - } - - let conditionValue; - let parentActive; - let block; - switch (tokens[0].toLowerCase()) { - case "!if": - case "!ifdef": - case "!ifndef": - this.conditionOpen.push({uri:documentUri, lineNo:lineIndex}); - switch(tokens[0].toLowerCase()){ - case "!if": - conditionValue = this.evaluateConditional(conditionStr, documentUri, lineIndex); - break; - case "!ifdef": - conditionValue = this.pushConditional(this.defines.isDefined(tokens[1])); - break; - case "!ifndef": - conditionValue = this.pushConditional(!this.defines.isDefined(tokens[1])); - break; - } - - // Determine if this block is active - parentActive = this.conditionStack.length === 0 || this.conditionStack[this.conditionStack.length - 1].active; - const active = parentActive && conditionValue; - - // Push new condition block - this.conditionStack.push({ active: active, satisfied: conditionValue }); - this.result.push(active); // This line is a control statement - break; - case "!elseif": - // Pop the last condition block - if (this.conditionStack.length === 0) { - //throw new Error('!elseif without !if'); - DiagnosticManager.error(documentUri, lineIndex, EdkDiagnosticCodes.conditionalMissform, "!elseif without !if"); - return true; - } - conditionValue = this.evaluateConditional(conditionStr, documentUri, lineIndex); - parentActive = this.conditionStack.length <= 1 || this.conditionStack[this.conditionStack.length - 2].active; - - // Update the top of the stack - block = this.conditionStack[this.conditionStack.length - 1]; - if (block.satisfied) { - // If already satisfied, this block is inactive - block.active = false; - } else { - // If not satisfied yet, check this condition - block.active = parentActive && conditionValue; - block.satisfied = conditionValue || block.satisfied; - } - this.result.push(block.active); // This line is a control statement - break; - case "!else": - if (this.conditionStack.length === 0) { - //throw new Error('!else without !if'); - DiagnosticManager.error(documentUri, lineIndex, EdkDiagnosticCodes.conditionalMissform, "!else without !if"); - return true; - } - parentActive = this.conditionStack.length <= 1 || this.conditionStack[this.conditionStack.length - 2].active; - - block = this.conditionStack[this.conditionStack.length - 1]; - if (block.satisfied) { - // If already satisfied, this block is inactive - block.active = false; - } else { - // Else block is active if parent is active and no previous condition satisfied - block.active = parentActive && !block.satisfied; - block.satisfied = true; - } - this.result.push(block.active); // This line is a control statement - break; - case "!endif": - - this.conditionOpen.pop(); - - if (this.conditionStack.length === 0) { - //throw new Error('!endif without !if'); - DiagnosticManager.error(documentUri, lineIndex, EdkDiagnosticCodes.conditionalMissform, "!endif without !if"); - return true; - } - - parentActive = this.conditionStack.length <= 1 || this.conditionStack[this.conditionStack.length - 2].active; - block = this.conditionStack[this.conditionStack.length - 1]; - - if (!parentActive) { - // If already satisfied, this block is inactive - this.result.push(false); - } else { - // Else block is active if parent is active and no previous condition satisfied - block.active = parentActive && !block.satisfied; - if(parentActive && block.satisfied){ - this.result.push(true); - }else{ - this.result.push(false); - } - } - this.conditionStack.pop(); - break; - default: - const isActive = this.conditionStack.every(block => block.active); - this.result.push(isActive); - } - - return this.result[this.result.length - 1]; - - - } - - private pushConditional(v: boolean) { - this.conditionalStack.push(v); - return v; - } - - evaluateExpression(expression: string): any { - const originalExpression = expression; - - // EDK sets undefined values as false - expression = expression.replaceAll(`"???"`, "FALSE"); - - // - // if(expression.includes(UNDEFINED_VARIABLE)){ - // gDebugLog.debug(`Evaluate expression: ${expression} -> ${false}`); - // return false; - // } - - // add space to parenteses - expression = expression.replaceAll(/\(/g, " ( "); - expression = expression.replaceAll(/\)/g, " ) "); - expression = expression.replaceAll(/\s+/g, " "); - - - let tokens = expression.match(/(?:[^\s"]+|"[^"]*")+/g) || []; - let outputQueue = []; - let operatorStack: string[] = []; - let parentesisBalance = 0; - for (const token of tokens) { - if (!isNaN(Number(token))) { - // Numbers - outputQueue.push(Number(token)); - } else if (token.toLowerCase() === 'true' || token.toLowerCase() === 'false') { - // Boolean values - outputQueue.push(token.toLowerCase() === 'true'); - } else if(token.trim().startsWith('"') && token.trim().endsWith('"')){ - // String values - outputQueue.push(token); - } else if (token in OPERATORS) { - // Operators - while (operatorStack.length && operatorStack[operatorStack.length - 1] in OPERATORS && - OPERATORS[token as keyof typeof OPERATORS].precedence <= OPERATORS[operatorStack[operatorStack.length - 1] as keyof typeof OPERATORS].precedence) { - outputQueue.push(operatorStack.pop()); - } - operatorStack.push(token); - } else if (token === '(') { - // Parentesis - parentesisBalance++; - operatorStack.push(token); - } else if (token === ')') { - // Parentesis - parentesisBalance--; - while (operatorStack.length && operatorStack[operatorStack.length - 1] !== '(') { - outputQueue.push(operatorStack.pop()); - } - operatorStack.pop(); - } else{ - // Strings without quotes - outputQueue.push(`"${token}"`); - // throw new Error(`Error evaluating expression: ${originalExpression} - bad Operand ${token}`); - } - } - - if(parentesisBalance !== 0){ - throw new Error(`Error evaluating expression: ${originalExpression} - Parenthesis balance error`); - } - - while (operatorStack.length) { - outputQueue.push(operatorStack.pop()); - } - - let stack: any[] = []; - for (const token of outputQueue) { - if (token! as keyof typeof OPERATORS in OPERATORS) { - let y = stack.pop() as never; - let x = stack.pop() as never; - stack.push(OPERATORS[token! as keyof typeof OPERATORS].fn(x, y)); - }else{ - stack.push(token); - } - } - - if(stack.length > 1){ - throw new Error(`Error evaluating expression: ${originalExpression}`); - } - - const retValue = (stack[0]===UNDEFINED_VARIABLE)? false : stack[0]; - gDebugLog.debug(`Evaluate expression: ${originalExpression} -> ${retValue}`); - return retValue; - } - - private evaluateConditional(text: string, documentUri:vscode.Uri, lineNo:number): any { - - - // let data = text.replaceAll(/(? associated with the INF file in the [Components] section - for (const library of dscLibDeclarations) { - if(library.parent === undefined){continue;} - let parentPaths = await gPathFind.findPath(library.parent); - for (const parentLocation of parentPaths) { - if(parentLocation.uri.fsPath === contextUri.fsPath){ - return [library]; - } - } - } - - // Return libraries that match module properties - - // Get MODULE_TYPE from original INF file - let infText = (await vscode.workspace.openTextDocument(contextUri)).getText(); - let m = /MODULE_TYPE\s*=\s*\b(\w*)\b/gi.exec(infText); - let moduleType = "common"; - if(m!==null){ - moduleType = m[1].toLocaleLowerCase(); - } - - //Get properties from moduleUri - let modulesDeclarations = await this.getDscDeclaration(contextUri); - let currentAccuracy = 0; - let locations = new Map(); - - // Check all module declarations. - for (const module of modulesDeclarations) { - let locationFound = false; - - // Module contains the properties obtained from DSC file. - // Here overwrite module type with the actual definition of the INF file - for (const property of module.sectionProperties.properties) { - property.moduleType = moduleType; - } - - for (const library of dscLibDeclarations) { - // 2. Library Class Instance that is defined in the [LibraryClasses.$(ARCH).$(MODULE_TYPE)] section will be used - - if(library.sectionProperties.compareArch(module.sectionProperties) && library.sectionProperties.compareModuleType(module.sectionProperties)){ - locationFound = true; - locations.set(library.path, library); - - break; - } - } - if(locationFound){continue;} - - for (const library of dscLibDeclarations) { - if(library.sectionProperties.compareArchStr("common") && library.sectionProperties.compareModuleType(module.sectionProperties)){ - locationFound = true; - locations.set(library.path, library); - break; - } - } - if(locationFound){continue;} - - // ? common.common - for (const library of dscLibDeclarations) { - if(library.sectionProperties.compareArchStr("common") && library.sectionProperties.compareModuleTypeStr("common")){ - locationFound = true; - locations.set(library.path, library); - break; - } - } - if(locationFound){continue;} - - - for (const library of dscLibDeclarations) { - // ?? just check for library classes - if(library.sectionProperties.compareLibSectionTypeStr("libraryclasses")){ - locationFound = true; - locations.set(library.path, library); - break; - } - } - if(locationFound){continue;} - - - gDebugLog.error(`Library ${libName} not found in ${module.path}`); - - } - return Array.from(locations.values()); - } - - -} \ No newline at end of file diff --git a/src/index/operations.ts b/src/index/operations.ts deleted file mode 100644 index 9ca6b97..0000000 --- a/src/index/operations.ts +++ /dev/null @@ -1,267 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { UNDEFINED_VARIABLE } from "./definitions"; - -export const OPERATORS = { - 'or': { precedence: 1, fn: _or }, - 'OR': { precedence: 1, fn: _or }, - '||': { precedence: 1, fn: _or }, - 'and': { precedence: 2, fn: _and}, - 'AND': { precedence: 2, fn: _and}, - '&&': { precedence: 2, fn: _and}, - '|': { precedence: 3, fn: _bitwise_or }, - '^': { precedence: 4, fn: _xor }, - '&': { precedence: 5, fn: _bitsiwe_and }, - '!=': { precedence: 6, fn: _not_equals}, - 'NE': { precedence: 6, fn: _not_equals}, - '==': { precedence: 6, fn: _equals }, - 'EQ': { precedence: 6, fn: _equals }, - '<=': { precedence: 7, fn: _lessOrEquals }, - '>=': { precedence: 7, fn: _greaterOrEquals }, - '<': { precedence: 7, fn: _lessThan }, - '>': { precedence: 7, fn: _greaterThan }, - '+': { precedence: 8, fn: _plus }, - '-': { precedence: 8, fn: _subtract}, - '*': { precedence: 9, fn: _times }, - '/': { precedence: 9, fn: _division }, - '%': { precedence: 9, fn: _module }, - '!': { precedence: 10, fn: _not }, - 'not': { precedence: 10, fn: _not }, - 'NOT': { precedence: 10, fn: _not }, - '~': { precedence: 10, fn: _bitwiseNot }, - '<<': { precedence: 11, fn: _leftShift }, - '>>': { precedence: 11, fn: _rightShift }, - 'in': { precedence: 12, fn: _in}, - 'IN': { precedence: 12, fn: _in}, -}; - - - -function boolToNumber(value: boolean): number { - if (typeof value !== 'boolean') { - return value; - } - return value ? 1 : 0; -} - -function _in(x:any, y: any) { - if (x === UNDEFINED_VARIABLE || y === UNDEFINED_VARIABLE) { - return false; - } - if(typeof x === 'string'){ - x = x.replaceAll('"', ''); - } - if(typeof y === 'string'){ - y = y.replaceAll('"', ''); - y = y.split(" "); - } - - if(y.includes){ - return y.includes(x); - } - return false; - -} - -function _bitwiseNot(y:any, x: number) { - if(validateSingle(x, 'number', '~')) { - return ~x; - } - return false; - -} - -function _lessThan(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '>')) { - return x > y; - } - return false; -} - -function _lessOrEquals(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '<=')) { - return x <= y; - } - return false; -} - -function _greaterThan(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '>')) { - return x > y; - } - return false; -} - -function _greaterOrEquals(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '>=')) { - return x >= y; - } - return false; -} - -function _leftShift(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '<<')) { - return x << y; - } - false; -} - -function _rightShift(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '>>')) { - return x >> y; - } - false; -} - -function _times(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '*')) { - return x * y; - } - return false; -} - -function _division(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '/')) { - if (y === 0) { - throw new Error(`Invalid expression: Division by zero.`); - } - return x / y; - } - - return false; -} - -function _module(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - - - - if(validate(x, y, 'number', '%')) { - if (y === 0) { - throw new Error(`Invalid expression: Module by zero.`); - } - return x % y; - } - - return false; -} - -function _plus(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - - if(validate(x, y, 'number', '+')) { - return x + y; - } - return false; -} - -function _subtract(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '-')) { - return x - y; - } - return false; -} - -function _xor(x:any, y: any) { - y = boolToNumber(y); - x = boolToNumber(x); - if(validate(x, y, 'number', '^')) { - return x ^ y; - } - return false; - -} - -function _bitwise_or(x:number, y: number) { - - if(validate(x, y, 'number', '|')) { - return x | y; - } - return false; - -} - -function _bitsiwe_and(x:number, y: number) { - if(validate(x, y, 'number', '&')) { - return x & y; - } - return false; - -} - -function _equals(x:any, y: any) { - if (x === UNDEFINED_VARIABLE || y === UNDEFINED_VARIABLE) { - return false; - } - return x === y; -} - -function _not_equals(x:any, y: any) { - if (x === UNDEFINED_VARIABLE || y === UNDEFINED_VARIABLE) { - return false; - } - return x !== y; -} - -function _not(y:any, x: boolean) { - if(validateSingle(x, 'boolean', 'not')) { - return !x; - } - return false; -} - -function _and(x:any, y: boolean) { - if (validate(x, y, 'boolean', 'and')) { - return x && y; - } - return false; -} - -function _or(x:any, y: boolean) { - - if(validate(x, y, 'boolean', 'or')) { - return x || y; - } - return false; - - -} - -function validateSingle(x:any, expected:string, operator:string) { - if (x === UNDEFINED_VARIABLE) { - return false; - } - if (typeof x !== expected) { - throw new Error(`Invalid expression: This operator cannot be used in ${typeof x} expression: [${operator}].`); - } - return true; -} - -function validate(x:any, y:any, expected:string, operator:string) { - if (x === UNDEFINED_VARIABLE || y === UNDEFINED_VARIABLE) { - return false; - } - if (typeof x !== expected || typeof y !== expected) { - throw new Error(`Invalid expression: This operator cannot be used in ${typeof x} ${operator} ${typeof y} expression: [${operator}].`); - } - return true; -} diff --git a/src/mapParser.ts b/src/mapParser.ts deleted file mode 100644 index 906ec6d..0000000 --- a/src/mapParser.ts +++ /dev/null @@ -1,100 +0,0 @@ -import * as fs from 'fs'; -import { gDebugLog } from './extension'; -import { readEdkCodeFolderFile } from './edk2CodeFolder'; - - -interface SymbolValue { - segment: number; - address: number; - name: string; - rvaBase: number; - libObject: string; -} - - - -export class MapFileData { - moduleName:string = ''; - symbolData: Map = new Map(); - - constructor(mapFilePath: string) { - if (!fs.existsSync(mapFilePath)) { - gDebugLog.warning(`Map file not found at ${mapFilePath}`); - return; - } - this.parseMapFile(mapFilePath); - } - - public isSymbolUsed(symbolName: string): boolean { - if (this.symbolData.has(symbolName)) { - return true; - } - return false; - } - - private parseMapFile(filePath: string) { - const content = fs.readFileSync(filePath, 'utf-8'); - const lines = content.split('\n'); - - this.moduleName = lines[0].trim(); - let isParseSymbols = false; - - for (let line of lines) { - line = line.trim(); - if(line.length === 0){continue;} - - // Look for start of symbols - if(!isParseSymbols){ - if(line.match(/Address\s*Publics by Value.*/gmi)){ - isParseSymbols = true; - } - continue; - } - - - // Parse symbols - let symbolMatch = /([a-f\d]+)\:([a-f\d]+)\s+(.*?)\s+([a-f\d]+)\s+(.*)/gmi.exec(line); - if(symbolMatch){ - const symbol: SymbolValue = { - segment: parseInt(symbolMatch[1].trim(),16), - address: parseInt(symbolMatch[2].trim(),16), - name: symbolMatch[3].trim(), - rvaBase: parseInt(symbolMatch[4].trim(),16), - libObject: symbolMatch[5].trim() - }; - this.symbolData.set(symbol.name, symbol); - continue; - } - } - - } -} - -export class MapFilesManager{ - mapFiles:Map = new Map(); - - constructor(){ - - } - - load() { - this.mapFiles = new Map(); - - const mapData = readEdkCodeFolderFile("mapFiles.json"); - if(mapData){ - const mapFiles = JSON.parse(mapData); - for(const mapFile of mapFiles){ - this.mapFiles.set(mapFile, new MapFileData(mapFile)); - } - } - } - - public isSymbolUsed(symbolName:string):boolean{ - for(const mapFile of this.mapFiles.values()){ - if(mapFile.isSymbolUsed(symbolName.split('(')[0].trim())){ - return true; - } - } - return false; - } -} \ No newline at end of file diff --git a/src/mcp/mcpServer.ts b/src/mcp/mcpServer.ts deleted file mode 100644 index 8d2c7a4..0000000 --- a/src/mcp/mcpServer.ts +++ /dev/null @@ -1,393 +0,0 @@ -import * as http from 'http'; -import * as vscode from 'vscode'; -import path = require('path'); -import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; -import { gDebugLog, gEdkWorkspaces, gPathFind, gWorkspacePath } from '../extension'; -import { openTextDocument } from '../utils'; -import { getParserForDocument } from '../edkParser/parserFactory'; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import { z } from 'zod'; - -let httpServer: http.Server | undefined; -let mcpServer: McpServer | undefined; -const transports: Record = {}; - -function createMcpServer(): McpServer { - const server = new McpServer( - { name: 'edk2code', version: '1.0.0' }, - { capabilities: { tools: {} } } - ); - - // ── Tool: list_files ──────────────────────────────────────────────── - server.registerTool( - 'list_edk2_workspace_files', - { - description: - 'List all files used in the EDK2 compilation across all loaded workspaces. ' + - 'Returns file names with their full paths. ' + - 'If a file you are looking for is not in this list, it is NOT used in the current compilation.', - inputSchema: { - fileName: z - .string() - .optional() - .describe( - 'Optional regex pattern to filter files by name (e.g. "Pci" to find all PCI-related files, "Pci.*\\.inf" for PCI .inf files). ' + - 'The pattern is matched case-insensitively against the file base name. ' + - 'If no match is found the file is not part of the current compilation.' - ), - }, - }, - async ({ fileName }) => { - const wps = gEdkWorkspaces.workspaces; - const allFiles: { name: string; fullPath: string }[] = []; - - for (const wp of wps) { - for (const filePath of wp.getFilesList()) { - allFiles.push({ - name: path.basename(filePath), - fullPath: filePath, - }); - } - } - - let results = allFiles; - if (fileName) { - try { - const regex = new RegExp(fileName, 'i'); - results = allFiles.filter((f) => regex.test(f.name)); - } catch { - // If invalid regex, fall back to substring match - const needle = fileName.toLowerCase(); - results = allFiles.filter( - (f) => f.name.toLowerCase().includes(needle) - ); - } - } - - if (results.length === 0) { - const msg = fileName - ? `File "${fileName}" was not found in any EDK2 workspace. It is not used in the current compilation.` - : 'No files found. The EDK2 workspace may not be indexed yet. Run "EDK2: Rebuild index database" first.'; - return { content: [{ type: 'text', text: msg }] }; - } - - const text = results - .map((f) => `${f.name}\t${f.fullPath}`) - .join('\n'); - return { content: [{ type: 'text', text }] }; - } - ); - - // ── Tool: resolve_edk2_file_path ──────────────────────────────────── - server.registerTool( - 'resolve_edk2_file_path', - { - description: - 'Resolve an EDK2 relative path or file name to its full filesystem path using the EDK2 path resolution logic. ' + - 'If the file cannot be resolved, it is not used in the current compilation.', - inputSchema: { - filePath: z - .string() - .describe( - 'The EDK2 relative path or file name to resolve (e.g. "MdeModulePkg/Core/Pei/PeiMain.inf").' - ), - }, - }, - async ({ filePath }) => { - const locations = await gPathFind.findPath(filePath); - if (locations.length === 0) { - return { - content: [ - { - type: 'text', - text: `Could not resolve "${filePath}". The file is not used in the current compilation or the workspace is not indexed.`, - }, - ], - }; - } - const text = locations.map((l) => l.uri.fsPath).join('\n'); - return { content: [{ type: 'text', text }] }; - } - ); - - // ── Tool: find_library_implementation ─────────────────────────────── - server.registerTool( - 'find_edk2_library_implementation', - { - description: - 'Find the implementation (INF file) of an EDK2 library by base name. ' + - 'Searches all loaded workspaces for library declarations in DSC files. ' + - 'Returns the library name, the INF path implementing it, the DSC location where it is declared, and the section properties (arch, module type). ' + - 'If no match is found, the library is not used in the current compilation.', - inputSchema: { - libraryName: z - .string() - .describe( - 'Library class name or regex pattern to search for (e.g. "BaseMemoryLib", "Pci.*Lib", "UefiBootServicesTableLib"). ' + - 'Matched case-insensitively against library class names declared in DSC files.' - ), - }, - }, - async ({ libraryName }) => { - const wps = gEdkWorkspaces.workspaces; - const results: string[] = []; - - let regex: RegExp | null = null; - try { - regex = new RegExp(libraryName, 'i'); - } catch { - // invalid regex, fall back to substring - } - - for (const wp of wps) { - for (const lib of wp.filesLibraries) { - const libNameDsc = lib.text.split('|')[0].trim(); - const matches = regex - ? regex.test(libNameDsc) - : libNameDsc.toLowerCase().includes(libraryName.toLowerCase()); - - if (matches) { - const resolvedPaths = await gPathFind.findPath(lib.path); - const fullPath = resolvedPaths.length - ? resolvedPaths[0].uri.fsPath - : lib.path; - const dscFile = lib.location.uri.fsPath; - const dscLine = lib.location.range.start.line + 1; - const section = lib.sectionProperties.toString() || 'unknown'; - results.push( - `${libNameDsc}\t${fullPath}\t${dscFile}:${dscLine}\t[${section}]` - ); - } - } - } - - if (results.length === 0) { - return { - content: [ - { - type: 'text', - text: `No library matching "${libraryName}" was found in any EDK2 workspace. It is not used in the current compilation.`, - }, - ], - }; - } - - const header = 'LibraryClass\tImplementation\tDSC Location\tSection'; - return { - content: [{ type: 'text', text: header + '\n' + results.join('\n') }], - }; - } - ); - - // ── Tool: find_inf_for_source ─────────────────────────────────────── - server.registerTool( - 'find_edk2_inf_for_source', - { - description: - 'Given a C/H source file, find the EDK2 INF file (library or component) that includes it in its [Sources] section. ' + - 'This is useful for determining which EDK2 module or library a source file belongs to. ' + - 'If no INF is found, the file may not be part of a compiled EDK2 component.', - inputSchema: { - sourceFile: z - .string() - .describe( - 'Full path or file name of a C/H source file (e.g. "PeiMain.c", "D:/edk2/MdeModulePkg/Core/Pei/PeiMain.c"). ' + - 'If only a file name is given, the tool will attempt to resolve it.' - ), - }, - }, - async ({ sourceFile }) => { - // Resolve to a URI - let fileUri: vscode.Uri; - if (path.isAbsolute(sourceFile)) { - fileUri = vscode.Uri.file(sourceFile); - } else { - const resolved = await gPathFind.findPath(sourceFile); - if (resolved.length === 0) { - return { - content: [{ - type: 'text', - text: `Could not resolve "${sourceFile}". The file was not found in the workspace.`, - }], - }; - } - fileUri = resolved[0].uri; - } - - const results: string[] = []; - - // Try indexed workspaces first (like gotoInf) - const wps = await gEdkWorkspaces.getWorkspace(fileUri); - if (wps.length) { - for (const wp of wps) { - const locations = await wp.getInfReference(fileUri); - for (const loc of locations) { - const infPath = loc.uri.fsPath; - const line = loc.range.start.line + 1; - if (!results.includes(infPath)) { - results.push(infPath); - } - } - } - } - - // Fallback: walk up from the source file looking for INF files - // that list it in their [Sources] section - if (results.length === 0) { - const fileName = path.basename(fileUri.fsPath); - const folderPath = path.dirname(fileUri.fsPath); - const workspaceRoot = gWorkspacePath; - - let currentDir = folderPath; - while (currentDir.length >= workspaceRoot.length) { - // Check all modules and libraries whose INF is relative to this dir - for (const wp of gEdkWorkspaces.workspaces) { - const allInfs = [...wp.filesModules, ...wp.filesLibraries]; - for (const inf of allInfs) { - const resolvedInf = await gPathFind.findPath(inf.path); - if (resolvedInf.length === 0) { continue; } - const infDir = path.dirname(resolvedInf[0].uri.fsPath); - if (!folderPath.startsWith(infDir)) { continue; } - try { - const doc = await openTextDocument(resolvedInf[0].uri); - const parser = await getParserForDocument(doc); - if (parser) { - const sources = parser.getSymbolsType(Edk2SymbolType.infSource); - for (const source of sources) { - const srcPath = await gPathFind.findPath( - await source.getValue(), - path.dirname(resolvedInf[0].uri.fsPath) - ); - if (srcPath.length && srcPath[0].uri.fsPath === fileUri.fsPath) { - const infFullPath = resolvedInf[0].uri.fsPath; - if (!results.includes(infFullPath)) { - results.push(infFullPath); - } - } - } - } - } catch { /* skip parse errors */ } - } - } - if (results.length > 0) { break; } - const parentDir = path.dirname(currentDir); - if (parentDir === currentDir) { break; } - currentDir = parentDir; - } - } - - if (results.length === 0) { - return { - content: [{ - type: 'text', - text: `No INF file found for "${sourceFile}". The file may not be part of a compiled EDK2 component or library.`, - }], - }; - } - - const text = results.map((infPath) => { - const name = path.basename(infPath, '.inf'); - return `${name}\t${infPath}`; - }).join('\n'); - return { - content: [{ type: 'text', text: `INF files for ${path.basename(sourceFile)}:\n${text}` }], - }; - } - ); - - return server; -} - -export async function startMcpServer(port: number): Promise { - if (httpServer) { - vscode.window.showInformationMessage(`MCP SSE server is already running on port ${port}`); - return; - } - - mcpServer = createMcpServer(); - - httpServer = http.createServer(async (req, res) => { - const url = new URL(req.url ?? '', `http://localhost:${port}`); - - // SSE stream endpoint - if (req.method === 'GET' && url.pathname === '/sse') { - gDebugLog.info('MCP SSE: new client connection'); - try { - const transport = new SSEServerTransport('/messages', res); - transports[transport.sessionId] = transport; - transport.onclose = () => { - gDebugLog.info(`MCP SSE: session ${transport.sessionId} closed`); - delete transports[transport.sessionId]; - }; - const server = createMcpServer(); - await server.connect(transport); - } catch (err) { - gDebugLog.error(`MCP SSE error: ${err}`); - if (!res.headersSent) { - res.writeHead(500); - res.end('Internal Server Error'); - } - } - return; - } - - // Message endpoint for client→server JSON-RPC - if (req.method === 'POST' && url.pathname === '/messages') { - const sessionId = url.searchParams.get('sessionId'); - if (!sessionId || !transports[sessionId]) { - res.writeHead(400); - res.end('Invalid or missing sessionId'); - return; - } - await transports[sessionId].handlePostMessage(req, res); - return; - } - - // Health check - if (req.method === 'GET' && url.pathname === '/health') { - res.writeHead(200, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ status: 'ok' })); - return; - } - - res.writeHead(404); - res.end('Not Found'); - }); - - return new Promise((resolve, reject) => { - httpServer!.listen(port, () => { - gDebugLog.info(`MCP SSE server listening on http://localhost:${port}/sse`); - vscode.window.showInformationMessage( - `EDK2 MCP SSE server started on http://localhost:${port}/sse` - ); - resolve(); - }); - httpServer!.on('error', (err) => { - gDebugLog.error(`MCP SSE server error: ${err}`); - vscode.window.showErrorMessage(`Failed to start MCP server: ${err.message}`); - httpServer = undefined; - reject(err); - }); - }); -} - -export function stopMcpServer(): void { - if (!httpServer) { - vscode.window.showInformationMessage('MCP SSE server is not running'); - return; - } - for (const id of Object.keys(transports)) { - transports[id].close(); - delete transports[id]; - } - httpServer.close(); - httpServer = undefined; - mcpServer = undefined; - gDebugLog.info('MCP SSE server stopped'); - vscode.window.showInformationMessage('EDK2 MCP SSE server stopped'); -} - -export function isMcpServerRunning(): boolean { - return httpServer !== undefined; -} diff --git a/src/moduleReport.ts b/src/moduleReport.ts deleted file mode 100644 index 21825ca..0000000 --- a/src/moduleReport.ts +++ /dev/null @@ -1,380 +0,0 @@ -import path = require("path"); -import { gModuleReport } from "./extension"; -import * as fs from 'fs'; -import { assert } from "console"; -import { normalizePath, pathCompare } from "./utils"; -import { getEdkCodeFolderFilePath } from "./edk2CodeFolder"; - - -export class EdkFile{ - data: any; - path:string; - constructor(data:any){ - this.data = data; - this.path = data["Path"]; - } -} - -export class EdkFunction{ - name: string; - constructor(name:string){ - this.name = name; - } -} - -export class EdkLibraryClass{ - data: any; - constructor(data:any){ - this.data = data; - } -} - -export class EdkLibrary{ - data: any; - path:string; - constructor(data:any){ - this.data = data; - this.path = data["Path"]; - } -} - -export class EdkGuid{ - data: any; - constructor(data:any){ - this.data = data; - } -} - -export class EdkPackage{ - data: any; - constructor(data:any){ - this.data = data; - } -} - -export class EdkPcd{ - data: any; - constructor(data:any){ - this.data = data; - } -} - -export class EdkModule{ - - - name:string; - arch:string; - path: string; - guid: string; - buildType: string; - isLibrary: string; - sourceDir: string; - files:EdkFile[] = []; - moduleEntryPointList: EdkFunction[]; - libraries: EdkLibrary[]; - constructorList: EdkFunction[]; - destructorList: EdkFunction[]; - packages: EdkPackage[]; - ppi: EdkGuid[]; - protocol: EdkGuid[]; - pcd: EdkPcd[]; - moduleReport: ModuleReport; - libraryClassName: string; - raw:any; - - - constructor(data:any){ - this.raw = data; - this.name = data["Name"]; - this.arch = data["Arch"]; - this.path = normalizePath(data["Path"]); - this.guid = data["Guid"]; - this.buildType = data["BuildType"]; - this.isLibrary = data["IsLibrary"]; - this.sourceDir = data["SourceDir"]; - this.moduleReport = gModuleReport; - if (data["LibraryClass"].length > 0){ - this.libraryClassName = data["LibraryClass"][0][0]; - }else{ - this.libraryClassName = ""; - } - - this.files = []; - for (const file of data["Files"]) { - this.files.push(new EdkFile(file)); - } - - // LibraryClass - - this.moduleEntryPointList = []; - for (const i of data["ModuleEntryPointList"]) { - this.moduleEntryPointList.push(new EdkFunction(i)); - } - - // constructor - this.constructorList = []; - for (const i of data["ConstructorList"]) { - this.constructorList.push(new EdkFunction(i)); - } - // destructor - this.destructorList = []; - for (const i of data["DestructorList"]) { - this.destructorList.push(new EdkFunction(i)); - } - - //libraries - this.libraries = []; - for (const i of data["Libraries"]) { - this.libraries.push(new EdkLibrary(i)); - } - - //packages - this.packages = []; - for (const i of data["Packages"]) { - this.packages.push(new EdkPackage(i)); - } - //ppi - this.ppi = []; - for (const i of data["PPI"]) { - this.ppi.push(new EdkGuid(i)); - } - //protocol - this.protocol = []; - for (const i of data["Protocol"]) { - this.protocol.push(new EdkGuid(i)); - } - //pcd - this.pcd = []; - for (const i of data["Pcd"]) { - this.pcd.push(new EdkPcd(i)); - } - - } - - - getInfLibrarySection(){ - return new EdkIniFile(this.path).getSection("LibraryClasses"); - } - - getLibrariesModules(){ - let librariesModules:EdkModule[] = []; - for (const lib of this.libraries) { - let libModule = this.moduleReport.getModule(lib.path); - if(libModule!==undefined){ - librariesModules.push(libModule); - }else{ - - } - - } - return librariesModules; - } - - - getUsages() { - let callers = []; - for (const mod of this.moduleReport.getModuleList()) { - if(mod.usesLibrary(this)){ - callers.push(mod); - } - } - return callers; - } - usesLibrary(module: EdkModule) { - for (const lib of this.libraries) { - if(pathCompare(lib.path,module.path)){ - return true; - } - } - return false; - } -} - -export class ModuleReport -{ - isPopulated: boolean = false; - private static instance: ModuleReport; - reportPath: string; - private data: any; - private moduleData:EdkModule[]; - private treeString: string =""; - - constructor(){ - this.reportPath = getEdkCodeFolderFilePath("module_report.json"); - this.moduleData = []; - this.load(); - } - - public static getInstance(){ - if(!ModuleReport.instance){ - ModuleReport.instance = new ModuleReport(); - } - return ModuleReport.instance; - } - - load(){ - this.moduleData = []; - if(!fs.existsSync(this.reportPath)){ - return; - } - let strData = fs.readFileSync(this.reportPath).toString(); - this.data = JSON.parse(strData); - - for (const d of this.data) { - this.moduleData.push(new EdkModule(d)); - } - - if(this.moduleData.length === 0){ - this.isPopulated = false; - }else{ - this.isPopulated = true; - } - - } - - getModuleInfo(path:string){ - for (const module of this.moduleData) { - if(pathCompare(module.path, path)){ - return module; - } - } - return undefined; - } - - getModule(path:string){ - let module; - if (path.toLocaleLowerCase().endsWith(".inf")) { - module = this.getModuleInfo(path); - } else { - module = this.searchModuleByFiles(path); - } - return module; - } - - getModuleList(){ - return this.moduleData; - } - - - getLibraryTree(target:EdkModule, context:EdkModule){ - assert(!context.isLibrary); - this.treeString=""; - let contextLibs = context.getLibrariesModules(); - let emptyList:any[] = []; - let reportObject = { - "name":"", - "path":"", - "children":emptyList, - "recursive":false - }; - this.getLibraryTreeRecursive(0, target,contextLibs, [], reportObject); - // showVirtualFile(`Library Tree: ${target.name}`, this.treeString); - return reportObject; - } - - private getLibraryTreeRecursive(deep:number,target:EdkModule, contextLibs:EdkModule[], - libraryTreesVisited:string[], reportObject:any){ - const tab = "\t".repeat(deep); - if(libraryTreesVisited.includes(target.path)){ - - reportObject["children"].push({ - "name":target.name, - "path":target.path.replaceAll(path.sep, "\\"+path.sep), - "children":[], - "recursive":true - }); - this.treeString += `${tab}${target.name} * ${target.path}\n`; - return; - } - libraryTreesVisited.push(target.path); - - let targetReport = { - "name":target.name, - "path":target.path, - "children":[], - "recursive":false - }; - reportObject["children"].push(targetReport); - - this.treeString += `${tab}${target.name} : ${target.path}\n`; - - let libraries = target.getInfLibrarySection(); - for (const lib of libraries) { - // look for EdkModule based on library name - let module = undefined; - for (const contextLib of contextLibs) { - if(contextLib.libraryClassName === lib || contextLib.name === lib){ - module = contextLib; - } - } - if(module === undefined){ - // This means this library is not compatible in this context - continue; - } - - this.getLibraryTreeRecursive(deep+1, module, contextLibs,libraryTreesVisited, targetReport); - } - } - - searchModuleByFiles(path:string){ - for (const module of this.getModuleList()) { - for (const moduleFile of module.files) { - if(pathCompare(moduleFile.path,path)){ - return module; - } - } - - } - return undefined; - } - -} - -export class EdkIniFile{ - path: string; - lines: string[]; - data: Map; - constructor(path:string){ - this.path = path; - assert(fs.existsSync(this.path)); - this.data = new Map(); - // Read lines uncommented - const lines = fs.readFileSync(this.path).toString().split(/\r?\n/); - this.lines = []; - for (let line of lines) { - line = line.trim(); - if(line.startsWith("#")){continue;} - if(line === ""){continue;} - this.lines.push(line.split('#')[0].trim()); - } - - let currentSection = undefined; - // loop on clean lines - for (const line of this.lines) { - if(line.startsWith("[")){ - let sectionName = line.replace("[","").replace("]",""); - if(!this.data.has(sectionName)){ - this.data.set(sectionName,[]); - currentSection = sectionName; - } - continue; - } - this.data.get(currentSection)?.push(line); - } - - } - - getSection(sectionName:string){ - sectionName = sectionName.toLocaleLowerCase(); - let returnData: string[] = []; - for (const section of this.data.keys()) { - if(section.split(".")[0].toLocaleLowerCase() === sectionName){ - const x = this.data.get(section); - if(x!==undefined){ - returnData = returnData.concat(x); - } - } - } - return returnData; - } -} \ No newline at end of file diff --git a/src/newVersionPage/1.1.0.md b/src/newVersionPage/1.1.0.md deleted file mode 100644 index 5ff6d3d..0000000 --- a/src/newVersionPage/1.1.0.md +++ /dev/null @@ -1,31 +0,0 @@ -# EDK2Code new version - -Thank you for installing the new version of the EDK2Code extension! 🎉 - -For detailed documentation, please visit: [EDK2Code Documentation](https://intel.github.io/Edk2Code/). - -You can find our GitHub repository here: [EDK2Code GitHub Repository](https://github.com/intel/Edk2Code). - -If you find this extension useful, please consider giving us a star on GitHub or leaving a review in the VSCode Marketplace. Your support is greatly appreciated! ⭐ - -# New features - -## [Module map](https://intel.github.io/Edk2Code/advance_features/#module-map) - -You can right click on a compiled INF file and select `EDK2: Show Module Map` - -![module-map-context-menu](https://intel.github.io/Edk2Code/images/module-map-context-menu.png) - -This will open the EDK2 submenu showing the libraries and source files that were used to compile that INF. - -![module-map](https://intel.github.io/Edk2Code/images/module-map.png) - -This feature is helpful in visualizing how a module includes various libraries. It also provides insights into how C files within the module include header files. By understanding these relationships, developers can better manage dependencies. - -## [Error Detection](https://intel.github.io/Edk2Code/advance_features/#error-detection) - -The DSC analysis can identify potential issues within the DSC files, such incorrect paths, duplicated libraries, etc. These issues are highlighted and shown in the Visual Studio Code "Problems" window. - -![55e73504-3e8b-4b58-a9fa-5fc64a89614f](https://intel.github.io/Edk2Code/images/55e73504-3e8b-4b58-a9fa-5fc64a89614f.png) - -You can disable this using the `edk2code.enableDiagnostics` setting \ No newline at end of file diff --git a/src/newVersionPage/2.0.0.md b/src/newVersionPage/2.0.0.md deleted file mode 100644 index 28d784f..0000000 --- a/src/newVersionPage/2.0.0.md +++ /dev/null @@ -1,81 +0,0 @@ -# EDK2Code 2.0.0 - -Thank you for installing the new version of the EDK2Code extension! 🎉 - -For detailed documentation, please visit: [EDK2Code Documentation](https://intel.github.io/Edk2Code/). - -You can find our GitHub repository here: [EDK2Code GitHub Repository](https://github.com/intel/Edk2Code). - -If you find this extension useful, please consider giving us a star on GitHub or leaving a review in the VSCode Marketplace. Your support is greatly appreciated! ⭐ - -# New features - -## Edk2Code sidebar - -The extension now lives in its own dedicated activity bar container, replacing the old `Edk2` panel under the Explorer view. You can find all Edk2Code views grouped together in the sidebar, including the new **Workspace** and **Module Info** views. - -## Workspace view - -The new **Workspace** view provides a unified, navigable representation of your parsed EDK2 workspace. It replaces the previous Module Map / Reference Tree / Library Tree commands with a single, persistent tree. - -Key capabilities: - -- **Sub-trees and includes** — DSC, INF, FDF and source files are organized hierarchically. Header includes and library sub-trees are integrated into the tree, so you can navigate dependencies in one place. -- **Search and filter** — Use the search action to quickly find nodes anywhere in the workspace tree. A dedicated filter is available to hide inactive (grayed-out) elements. -- **Reveal active editor** — Jump from the currently open file to its location in the workspace tree. -- **Drag and drop** — Reorganize and rearrange tree nodes via drag and drop. -- **Multiple workspaces** — When multiple build configurations are loaded, you can switch between them from the view title bar. Searching for symbols automatically switches to the workspace that owns the result. -- **Copy node path / Copy tree** — Quickly copy the path of a node or export the entire tree as text. -- **Welcome view** — When no workspace is loaded, the view guides you through discovering build folders or opening the configuration UI. - -## Module Info view - -The new **Module Info** view shows the EDK2 module information for the file you are currently editing. As soon as you open a C, INF or related source file that belongs to a module, the view populates with: - -- The owning INF and DSC declaration -- Libraries linked to the module -- Quick navigation actions (go to definition, open file, go to DSC declaration) - -Double-click any entry to jump directly to the corresponding source location. - -## Build folder auto-discovery - -EDK2Code can now scan your workspace and automatically detect existing build output folders. - -- Run **`EDK2: Discover build folders`** to scan the workspace. -- Once discovered, run **`EDK2: Use discovered build folders`** to load them directly — no manual configuration needed. -- The Workspace view welcome page surfaces these actions when nothing is loaded yet. - -## Compile EDK2 file - -You can now compile an individual EDK2 file (e.g. a `.c` belonging to a module) directly from the editor. - -- A play (▶) icon is shown on supported source files. -- The command **`EDK2: Compile Edk2 file`** invokes the build for the parent module of the active file. - -## MCP server integration - -EDK2Code now exposes an **MCP (Model Context Protocol) SSE server** that lets AI agents and external tools query your parsed EDK2 workspace. - -- Start with **`EDK2: Start MCP SSE Server`** and stop with **`EDK2: Stop MCP SSE Server`**. -- The server port is configurable via the `edk2code.mcpServerPort` setting (default `3100`). - -## Settings UI - -A graphical **Workspace configuration (UI)** panel has been added to make managing build configurations easier. Launch it from the Workspace view title bar (`$(gear)` icon) or via the **`EDK2: Workspace configuration (UI)`** command — no more hand-editing JSON for common setups. - -## Goto overwriting definition - -When a symbol is overwritten in a DSC (libraries, PCDs, modules), a new code action lets you jump directly to the overwriting definition. - -## Other improvements - -- **Disable cscope** — A new `edk2code.useCscope` setting lets you turn off cscope integration entirely. When disabled, the cscope database is not built or queried. -- **Unload workspace** — New `EDK2: Unload workspace` command to clear the currently loaded build configuration. -- **Refresh workspace config** — Reload the workspace configuration without restarting VS Code. -- **Focus INF from C files** — Improved navigation from C source files back to their owning INF module. -- **Better module symbols** — DSC parser now recognizes module sub-context sections, build options, and improved symbols for libraries and modules. -- **Loading and discovery indicators** — Progress indicators are shown while the workspace is being parsed or build folders are being discovered. -- **Improved grayout controller** — Inactive code regions are computed and updated more reliably. -- **Path improvements** — Missing paths now report folders instead of file names, and tooltips include the full path. -- **Extensive test suite** — New parser and workspace tests covering ASL, DEC, DSC, FDF, INF and VFR. diff --git a/src/newVersionPage/newVersionMessage.ts b/src/newVersionPage/newVersionMessage.ts deleted file mode 100644 index 9c1ae46..0000000 --- a/src/newVersionPage/newVersionMessage.ts +++ /dev/null @@ -1,18 +0,0 @@ -import getCurrentVersion from "../utils"; -import * as vscode from 'vscode'; -import * as path from 'path'; -import * as fs from 'fs'; - -export async function showReleaseNotes(context: vscode.ExtensionContext){ - const CURRENT_VERSION = getCurrentVersion(); - const previousVersion = context.globalState.get('extensionVersion'); - if (previousVersion !== CURRENT_VERSION) { - await context.globalState.update('extensionVersion', CURRENT_VERSION); - - const releaseNotesPath = path.join(context.extensionPath, 'src', 'newVersionPage', `${CURRENT_VERSION}.md`); - if (fs.existsSync(releaseNotesPath)) { - const releaseNotesUri = vscode.Uri.file(releaseNotesPath); - await vscode.commands.executeCommand('markdown.showPreview', releaseNotesUri); - } - } -} \ No newline at end of file diff --git a/src/pathfind.ts b/src/pathfind.ts deleted file mode 100644 index 7add752..0000000 --- a/src/pathfind.ts +++ /dev/null @@ -1,219 +0,0 @@ -import path = require("path"); -import * as fs from 'fs'; -import * as vscode from 'vscode'; -import glob = require("fast-glob"); - -import { gConfigAgent, gDebugLog, gWorkspacePath } from "./extension"; -import { REGEX_VAR_USAGE } from "./edkParser/commonParser"; -import { toPosix, getRealPathRelative } from "./utils"; - -export class PathFind{ - - static inProgress = false; - - extensions = [ - ".c", - ".h", - ".asl", - ".asi", - ".aslc", - ".i", - ".ii", - ".iii", - ".iiii", - ".dsc", - ".dsc.inc", - ".dec", - ".dec.inc", - ".dec.template", - ".vfr", - ".Vfr", - ".hfr", - ".fdf", - ".fdf.inc", - ".inf", - ".uni", - ".nasm", - ".asm" -]; - - - private missingPaths: string[] = []; - - async findPath(pathArg: string, relativePath: string|undefined = "") { - pathArg = pathArg.replaceAll(/(\\+|\/+)/gi, path.sep); - gDebugLog.trace(`Looking for: ${pathArg}`); - - // Restrict path characters - if (pathArg.match(/[\[\]\#\%\&\{\}\<\>\*\?\!\'\@\|\‘\`\“,'"'\^]/gi)) { - return []; - } - - //Check that pathArg doesnt ends with a variable - if(pathArg.match(/\$\(\s*.*?\s*\)\s*$/gi)){ - return []; - } - - if (pathArg.length === 0) { - return []; - } - - if(this.isKnownMissing(pathArg)){ - return []; - } - - if (path.isAbsolute(pathArg)) { - if (fs.existsSync(pathArg)) { - return this.produceLocation(pathArg); - } - return []; - } - - if (relativePath) { - const location = await this.findRelativePath(pathArg, relativePath); - if(location){ - return [location]; - } - } - - if (fs.existsSync(path.join(gWorkspacePath, pathArg))) { - return this.produceLocation(path.join(gWorkspacePath, pathArg)); - } - - // Check on workspace relative paths - let packagePaths = gConfigAgent.getBuildPackagePaths(); - for (const relPath of packagePaths) { - let p = path.join(relPath, pathArg); - if (fs.existsSync(p)) { - return this.produceLocation(p); - } - } - - - - - - gDebugLog.warning(`Global find: ${pathArg}`); - - let normalizedArg = pathArg.replaceAll('\\', '/').replaceAll(REGEX_VAR_USAGE, '**'); - // Search by filename only (like Ctrl+P), then filter by path suffix - let fileName = path.basename(pathArg); - - // If a temporary T-tree index exists (workspace is being rebuilt - // after a clear) use it for an instant lookup; otherwise fall - // back to the normal vscode.workspace.findFiles API. - const fileIndex = gConfigAgent.getFileIndex(); - let paths: vscode.Uri[]; - if (fileIndex) { - paths = fileIndex.findFilesByName(fileName); - } else { - paths = await vscode.workspace.findFiles(`**/${fileName}`, null); - } - - // Filter results that match the full path pattern - let filteredPaths = paths.filter(p => { - let normalizedFsPath = p.fsPath.replaceAll('\\', '/'); - // Build a regex from the normalized path arg, replacing ** with .* - let patternStr = normalizedArg.replaceAll('**', '.*').replace(/[.*+?^${}()|[\]\\]/g, (m) => m === '.*' ? '.*' : '\\' + m); - // Re-apply .* for the glob wildcards after escaping - patternStr = normalizedArg.split('**').map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('.*'); - return new RegExp(patternStr + '$', 'i').test(normalizedFsPath); - }); - - // If no filtered results but we had unfiltered results, use filename matches as fallback - if(filteredPaths.length === 0 && paths.length > 0){ - filteredPaths = paths; - } - - let retPath = []; - for (const p of filteredPaths) { - retPath.push(new vscode.Location(vscode.Uri.file(p.fsPath), new vscode.Position(0, 0))); - - // Add dinamyc include paths - let newPath = p.fsPath.slice(0,p.fsPath.length - pathArg.length - 1); - gConfigAgent.pushBuildPackagePaths(getRealPathRelative(newPath)); - } - - if(retPath.length === 0){ - gDebugLog.warning(`Missing file: ${pathArg}`); - this.addMissingPath(pathArg); - } - - return retPath; - - } - - async findRelativePath(pathArg: string, relativePath: string){ - if (relativePath) { - if (fs.existsSync(relativePath) && fs.statSync(relativePath).isFile()) { - relativePath = path.dirname(relativePath); - } - let p = path.join(relativePath, pathArg); - if (fs.existsSync(p)) { - return new vscode.Location(vscode.Uri.file(p), new vscode.Position(0, 0)); - } - } - } - - /** - * Check if pathArg (or any of its parent segments) is already known to be missing. - */ - private isKnownMissing(pathArg: string): boolean { - const normalized = toPosix(pathArg); - return this.missingPaths.some(missing => { - return normalized === missing || normalized.startsWith(missing + '/'); - }); - } - - /** - * Walk up parent directories of pathArg and find the highest-level - * directory that doesn't exist in the workspace or package paths. - * Cache that root so all future lookups under it are skipped. - */ - private addMissingPath(pathArg: string): void { - // Don't add if already covered by an existing missing path - if (this.isKnownMissing(pathArg)) { - return; - } - - const posixPath = toPosix(pathArg); - const parts = posixPath.split('/'); - let missingRoot = posixPath; - - // Walk from the top-level segment downward; find the first parent that - // does NOT exist anywhere, and cache that instead of the full path. - for (let i = 1; i < parts.length; i++) { - const parentPath = parts.slice(0, i).join(path.sep); - if (!this.parentExistsInWorkspace(parentPath)) { - missingRoot = parentPath; - break; - } - } - - gDebugLog.trace(`Caching missing path: ${missingRoot}`); - this.missingPaths.push(toPosix(missingRoot)); - } - - /** - * Check whether a relative directory exists under the workspace root - * or any of the configured package paths. - */ - private parentExistsInWorkspace(parentPath: string): boolean { - if (fs.existsSync(path.join(gWorkspacePath, parentPath))) { - return true; - } - const packagePaths = gConfigAgent.getBuildPackagePaths(); - for (const relPath of packagePaths) { - if (fs.existsSync(path.join(relPath, parentPath))) { - return true; - } - } - return false; - } - - produceLocation(path:string){ - return [new vscode.Location(vscode.Uri.file(path), new vscode.Position(0, 0))]; - } - - -} \ No newline at end of file diff --git a/src/rg.ts b/src/rg.ts deleted file mode 100644 index 4fad83d..0000000 --- a/src/rg.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { CancellationToken, Location, Range, Uri } from "vscode"; -import { gDebugLog, gWorkspacePath } from "./extension"; -import {rgPath} from "@vscode/ripgrep"; -import { createRange, exec, makeRelativeToWs } from "./utils"; -import * as edkStatusBar from './statusBar'; -import path = require("path"); - - - -export async function rgSearch(text:string, includeExt:string[]=[], filesPath:string[]=[], relative=false){ - return new Promise(async (resolve, reject) => { - - let command = `${rgPath} ${text} `; - - - - for (const f of filesPath) { - command += makeRelativeToWs(f) + " "; - } - - for (const f of includeExt) { - command += " -g " + f; - } - - if(relative){ - command += " ./ "; - } - - command += " --hidden --follow --crlf --no-config --json"; - - if(filesPath.length===0 && !relative){ - command += " -- ./"; - } - - gDebugLog.trace(command); - let textResult=""; - try { - edkStatusBar.setWorking(); - textResult = await exec(command, gWorkspacePath); - edkStatusBar.clearWorking(); - } catch (error) { - gDebugLog.trace(`rgSearch: ${error}`); - resolve([]); - } - - gDebugLog.trace(textResult); - let locations:Location[] = []; - for (const jsonData of textResult.split('\n')) { - if(jsonData===""){continue;} - let data = JSON.parse(jsonData); - if("type" in data && data["type"]==="match"){ - let uri = Uri.file(path.join(gWorkspacePath, data["data"]["path"]["text"])); - locations.push(new Location(uri,createRange(data["data"]["line_number"],data["data"]["line_number"]-1))); - } - } - resolve(locations); - }); - - -} - -export async function rgSearchText(text:string, includeExt:string[]=[], filesPath:string[]=[], relative=false){ - return new Promise(async (resolve, reject) => { - - let command = `${rgPath} ${text} `; - - for (const f of filesPath) { - command += makeRelativeToWs(f) + " "; - } - - for (const f of includeExt) { - command += " -g " + f; - } - - if(relative){ - command += " ./ "; - } - - command += " --hidden --follow --crlf --no-config --json"; - - if(filesPath.length===0 && !relative){ - command += " -- ./"; - } - - gDebugLog.trace(command); - let textResult=""; - try { - edkStatusBar.setWorking(); - textResult = await exec(command, gWorkspacePath); - edkStatusBar.clearWorking(); - } catch (error) { - gDebugLog.trace(`rgSearch: ${error}`); - resolve([]); - } - - gDebugLog.trace(textResult); - let textMatches:string[] = []; - for (const jsonData of textResult.split('\n')) { - if(jsonData===""){continue;} - let data = JSON.parse(jsonData); - if("type" in data && data["type"]==="match"){ - textMatches.push(data["data"]["lines"].text); - - } - } - resolve(textMatches); - }); - - -} \ No newline at end of file diff --git a/src/settings/settings.html b/src/settings/settings.html deleted file mode 100644 index 7cf3a4c..0000000 --- a/src/settings/settings.html +++ /dev/null @@ -1,636 +0,0 @@ - - - - - - - - - - - - - - - - - -
- - -
-
EDK2 Workspace Configurations
-
- Use this editor to Workspaces configuration edk_properties.json file. Changes made in this editor only apply to the selected configuration. To edit multiple configurations at once go to edk_properties.json. -
-
- -
-
- - -
-
MCP Server
-
- Control the EDK2 MCP SSE server and configure workspace MCP integration. -
-
- - -
-
- - -
-
- - -
-
- - -
-
DSC relative path
-
- Main DSC file relative paths. This are the DSC files used for your platform. In your build log you will see this as Active Platform -
-
-
Add .dsc files used for your platform.
-
- -
-
-
- -
-
Build Defines
-
- Build definitions injected on build command. Usually this are the -D arguments on your build command -
-
-
Define/value pairs passed as -D arguments.
-
-
- - - -
-
-
-
- -
-
Package paths
-
- Workspace relative package paths. This is what you see in your build log as PACKAGES_PATH env variable. -
-
-
Add workspace-relative package paths.
-
- -
-
-
- - - - - - - -
- - - - - diff --git a/src/settings/settings.ts b/src/settings/settings.ts deleted file mode 100644 index 9841f81..0000000 --- a/src/settings/settings.ts +++ /dev/null @@ -1,491 +0,0 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -'use strict'; - -const elementId: { [key: string]: string } = { - // Basic settings - dscPaths: "dscPaths", - dscPathsList: "dscPathsList", - dscAddBtn: "dscAddBtn", - buildDefines: "buildDefines", - buildDefinesList: "buildDefinesList", - buildDefinesAddBtn: "buildDefinesAddBtn", - buildDefineNewName: "buildDefineNewName", - buildDefineNewValue: "buildDefineNewValue", - packagePaths: "packagePaths", - packagePathsList: "packagePathsList", - packagePathsAddBtn: "packagePathsAddBtn", - -}; - -interface VsCodeApi { - postMessage(msg: Record): void; - setState(state: Record): void; - getState(): any; -} - -declare function acquireVsCodeApi(): VsCodeApi; - -class SettingsApp { - private readonly vsCodeApi: VsCodeApi; - private updating: boolean = false; - private dscPaths: string[] = []; - private buildDefines: {name: string, value: string}[] = []; - private packagePaths: string[] = []; - - constructor() { - this.vsCodeApi = acquireVsCodeApi(); - window.addEventListener("keydown", this.onTabKeyDown.bind(this)); - window.addEventListener("message", this.onMessageReceived.bind(this)); - - // Add event listeners to UI elements - - this.addEventsToInputValues(); - this.addDscListEvents(); - this.addBuildDefinesEvents(); - this.addPackagePathsEvents(); - this.addMcpEvents(); - this.vsCodeApi.postMessage({ - command: "initialized" - }); - } - - private addDscListEvents(): void { - document.getElementById(elementId.dscAddBtn)!.addEventListener("click", () => { - this.vsCodeApi.postMessage({ command: "selectDscFile" }); - }); - } - - // --- MCP --- - - private addMcpEvents(): void { - document.getElementById("mcpToggleBtn")!.addEventListener("click", () => { - this.vsCodeApi.postMessage({ command: "toggleMcp" }); - }); - document.getElementById("mcpAutoConfigBtn")!.addEventListener("click", () => { - this.vsCodeApi.postMessage({ command: "autoConfigureMcp" }); - }); - document.getElementById("mcpPort")!.addEventListener("change", () => { - const port = parseInt((document.getElementById("mcpPort")).value, 10); - if (port >= 1 && port <= 65535) { - this.vsCodeApi.postMessage({ command: "changeMcpPort", port }); - } - }); - } - - private updateMcpStatus(running: boolean): void { - const btn = document.getElementById("mcpToggleBtn") as HTMLButtonElement; - const status = document.getElementById("mcpStatus")!; - if (running) { - btn.textContent = "Stop MCP Server"; - status.textContent = "Running"; - status.style.color = "var(--vscode-charts-green)"; - } else { - btn.textContent = "Start MCP Server"; - status.textContent = "Stopped"; - status.style.color = "var(--vscode-foreground)"; - } - } - - private updateMcpConfigStatus(message: string): void { - document.getElementById("mcpConfigStatus")!.textContent = message; - } - - private renderDscList(): void { - const container = document.getElementById(elementId.dscPathsList)!; - container.innerHTML = ""; - this.dscPaths.forEach((path, index) => { - const item = document.createElement("div"); - item.className = "dsc-list-item"; - - const pathSpan = document.createElement("span"); - pathSpan.className = "dsc-path"; - pathSpan.textContent = path; - item.appendChild(pathSpan); - - const editBtn = document.createElement("button"); - editBtn.type = "button"; - editBtn.textContent = "Edit"; - editBtn.addEventListener("click", () => this.editDscItem(index)); - item.appendChild(editBtn); - - const deleteBtn = document.createElement("button"); - deleteBtn.type = "button"; - deleteBtn.textContent = "Delete"; - deleteBtn.addEventListener("click", () => this.deleteDscItem(index)); - item.appendChild(deleteBtn); - - container.appendChild(item); - }); - } - - private editDscItem(index: number): void { - const container = document.getElementById(elementId.dscPathsList)!; - const item = container.children[index] as HTMLElement; - const currentPath = this.dscPaths[index]; - - item.innerHTML = ""; - const input = document.createElement("input"); - input.type = "text"; - input.className = "dsc-edit-input"; - input.value = currentPath; - item.appendChild(input); - - const saveBtn = document.createElement("button"); - saveBtn.type = "button"; - saveBtn.textContent = "Save"; - saveBtn.addEventListener("click", () => { - this.dscPaths[index] = input.value; - this.renderDscList(); - this.onDscPathsChanged(); - }); - item.appendChild(saveBtn); - - const cancelBtn = document.createElement("button"); - cancelBtn.type = "button"; - cancelBtn.textContent = "Cancel"; - cancelBtn.addEventListener("click", () => this.renderDscList()); - item.appendChild(cancelBtn); - - input.focus(); - } - - private deleteDscItem(index: number): void { - this.dscPaths.splice(index, 1); - this.renderDscList(); - this.onDscPathsChanged(); - } - - private onDscPathsChanged(): void { - if (this.updating) { return; } - this.vsCodeApi.postMessage({ - command: "change", - config: this.collectConfig() - }); - } - - // --- Build Defines --- - - private addBuildDefinesEvents(): void { - document.getElementById(elementId.buildDefinesAddBtn)!.addEventListener("click", () => { - const nameInput = document.getElementById(elementId.buildDefineNewName); - const valueInput = document.getElementById(elementId.buildDefineNewValue); - const name = nameInput.value.trim(); - const value = valueInput.value.trim(); - if (name) { - this.buildDefines.push({ name, value }); - this.renderBuildDefinesList(); - this.onBuildDefinesChanged(); - nameInput.value = ""; - valueInput.value = ""; - } - }); - } - - private renderBuildDefinesList(): void { - const container = document.getElementById(elementId.buildDefinesList)!; - container.innerHTML = ""; - this.buildDefines.forEach((def, index) => { - const item = document.createElement("div"); - item.className = "define-list-item"; - - const nameSpan = document.createElement("span"); - nameSpan.className = "define-name"; - nameSpan.textContent = def.name; - item.appendChild(nameSpan); - - const valueSpan = document.createElement("span"); - valueSpan.className = "define-value"; - valueSpan.textContent = def.value; - item.appendChild(valueSpan); - - const editBtn = document.createElement("button"); - editBtn.type = "button"; - editBtn.textContent = "Edit"; - editBtn.addEventListener("click", () => this.editBuildDefineItem(index)); - item.appendChild(editBtn); - - const deleteBtn = document.createElement("button"); - deleteBtn.type = "button"; - deleteBtn.textContent = "Delete"; - deleteBtn.addEventListener("click", () => this.deleteBuildDefineItem(index)); - item.appendChild(deleteBtn); - - container.appendChild(item); - }); - } - - private editBuildDefineItem(index: number): void { - const container = document.getElementById(elementId.buildDefinesList)!; - const item = container.children[index] as HTMLElement; - const current = this.buildDefines[index]; - - item.innerHTML = ""; - const nameInput = document.createElement("input"); - nameInput.type = "text"; - nameInput.className = "define-edit-input"; - nameInput.value = current.name; - item.appendChild(nameInput); - - const valueInput = document.createElement("input"); - valueInput.type = "text"; - valueInput.className = "define-edit-input"; - valueInput.value = current.value; - item.appendChild(valueInput); - - const saveBtn = document.createElement("button"); - saveBtn.type = "button"; - saveBtn.textContent = "Save"; - saveBtn.addEventListener("click", () => { - this.buildDefines[index] = { name: nameInput.value.trim(), value: valueInput.value.trim() }; - this.renderBuildDefinesList(); - this.onBuildDefinesChanged(); - }); - item.appendChild(saveBtn); - - const cancelBtn = document.createElement("button"); - cancelBtn.type = "button"; - cancelBtn.textContent = "Cancel"; - cancelBtn.addEventListener("click", () => this.renderBuildDefinesList()); - item.appendChild(cancelBtn); - - nameInput.focus(); - } - - private deleteBuildDefineItem(index: number): void { - this.buildDefines.splice(index, 1); - this.renderBuildDefinesList(); - this.onBuildDefinesChanged(); - } - - private onBuildDefinesChanged(): void { - if (this.updating) { return; } - this.vsCodeApi.postMessage({ - command: "change", - config: this.collectConfig() - }); - } - - // --- Package Paths --- - - private addPackagePathsEvents(): void { - document.getElementById(elementId.packagePathsAddBtn)!.addEventListener("click", () => { - this.vsCodeApi.postMessage({ command: "selectPackagePath" }); - }); - } - - private renderPackagePathsList(): void { - const container = document.getElementById(elementId.packagePathsList)!; - container.innerHTML = ""; - this.packagePaths.forEach((p, index) => { - const item = document.createElement("div"); - item.className = "pkg-list-item"; - - const pathSpan = document.createElement("span"); - pathSpan.className = "pkg-path"; - pathSpan.textContent = p; - item.appendChild(pathSpan); - - const editBtn = document.createElement("button"); - editBtn.type = "button"; - editBtn.textContent = "Edit"; - editBtn.addEventListener("click", () => this.editPackagePathItem(index)); - item.appendChild(editBtn); - - const deleteBtn = document.createElement("button"); - deleteBtn.type = "button"; - deleteBtn.textContent = "Delete"; - deleteBtn.addEventListener("click", () => this.deletePackagePathItem(index)); - item.appendChild(deleteBtn); - - container.appendChild(item); - }); - } - - private editPackagePathItem(index: number): void { - const container = document.getElementById(elementId.packagePathsList)!; - const item = container.children[index] as HTMLElement; - const currentPath = this.packagePaths[index]; - - item.innerHTML = ""; - const input = document.createElement("input"); - input.type = "text"; - input.className = "pkg-edit-input"; - input.value = currentPath; - item.appendChild(input); - - const saveBtn = document.createElement("button"); - saveBtn.type = "button"; - saveBtn.textContent = "Save"; - saveBtn.addEventListener("click", () => { - this.packagePaths[index] = input.value; - this.renderPackagePathsList(); - this.onPackagePathsChanged(); - }); - item.appendChild(saveBtn); - - const cancelBtn = document.createElement("button"); - cancelBtn.type = "button"; - cancelBtn.textContent = "Cancel"; - cancelBtn.addEventListener("click", () => this.renderPackagePathsList()); - item.appendChild(cancelBtn); - - input.focus(); - } - - private deletePackagePathItem(index: number): void { - this.packagePaths.splice(index, 1); - this.renderPackagePathsList(); - this.onPackagePathsChanged(); - } - - private onPackagePathsChanged(): void { - if (this.updating) { return; } - this.vsCodeApi.postMessage({ - command: "change", - config: this.collectConfig() - }); - } - - private collectConfig(): any { - const elements: NodeListOf = document.getElementsByName("inputValue"); - let config: any = {}; - elements.forEach(el => { - const data: HTMLInputElement = document.getElementById(el.id); - config[data.id] = data.value; - }); - config[elementId.dscPaths] = this.dscPaths.join("\n"); - config[elementId.buildDefines] = this.buildDefines.map(d => `${d.name}=${d.value}`).join("\n"); - config[elementId.packagePaths] = this.packagePaths.join("\n"); - return config; - } - - private addEventsToInputValues(): void { - const elements: NodeListOf = document.getElementsByName("inputValue"); - elements.forEach(el => { - el.addEventListener("change", this.onChanged.bind(this, el.id)); - }); - } - - - - private onTabKeyDown(e: any): void { - if (e.keyCode === 9) { - document.body.classList.add("tabbing"); - window.removeEventListener("keydown", this.onTabKeyDown); - window.addEventListener("mousedown", this.onMouseDown.bind(this)); - } - } - - private onMouseDown(): void { - document.body.classList.remove("tabbing"); - window.removeEventListener("mousedown", this.onMouseDown); - window.addEventListener("keydown", this.onTabKeyDown.bind(this)); - } - - - private onChanged(id: string): void { - if (this.updating) { - return; - } - - this.vsCodeApi.postMessage({ - command: "change", - config: this.collectConfig() - }); - } - - private onMessageReceived(e: MessageEvent): void { - const message: any = e.data; // The json data that the extension sent - switch (message.command) { - case 'updateConfig': - this.updateConfig(message.config); - break; - case 'updateErrors': - this.updateErrors(message.errors); - break; - case 'addDscFile': - if (message.path && !this.dscPaths.includes(message.path)) { - this.dscPaths.push(message.path); - this.renderDscList(); - this.onDscPathsChanged(); - } - break; - case 'addPackagePath': - if (message.path && !this.packagePaths.includes(message.path)) { - this.packagePaths.push(message.path); - this.renderPackagePathsList(); - this.onPackagePathsChanged(); - } - break; - case 'mcpStatus': - this.updateMcpStatus(message.running); - if (message.port !== undefined) { - (document.getElementById("mcpPort")).value = message.port.toString(); - } - break; - case 'mcpConfigResult': - this.updateMcpConfigStatus(message.message); - break; - } - } - - private updateConfig(config: any): void { - this.updating = true; - try { - // DSC paths - this.dscPaths = (config.dscPaths && config.dscPaths.length) ? [...config.dscPaths] : []; - this.renderDscList(); - - // Build defines (stored as "name=value" strings) - if (config.buildDefines && config.buildDefines.length) { - this.buildDefines = config.buildDefines.map((entry: string) => { - const eqIdx = entry.indexOf("="); - if (eqIdx >= 0) { - return { name: entry.substring(0, eqIdx), value: entry.substring(eqIdx + 1) }; - } - return { name: entry, value: "" }; - }); - } else { - this.buildDefines = []; - } - this.renderBuildDefinesList(); - - // Package paths - this.packagePaths = (config.packagePaths && config.packagePaths.length) ? [...config.packagePaths] : []; - this.renderPackagePathsList(); - - } finally { - this.updating = false; - } - } - - private updateErrors(errors: any): void { - this.updating = true; - try { - this.showErrorWithInfo(elementId.configNameInvalid, errors.name); - this.showErrorWithInfo(elementId.configNameInvalid, errors.name); - this.showErrorWithInfo(elementId.configNameInvalid, errors.name); - } finally { - this.updating = false; - } - } - - private showErrorWithInfo(elementID: string, errorInfo: string): void { - this.showElement(elementID, errorInfo ? true : false); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - document.getElementById(elementID)!.innerHTML = errorInfo ? errorInfo : ""; - } - - - - private showElement(elementID: string, show: boolean): void { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - document.getElementById(elementID)!.style.display = show ? "block" : "none"; - } -} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const app: SettingsApp = new SettingsApp(); diff --git a/src/settings/settingsPanel.ts b/src/settings/settingsPanel.ts deleted file mode 100644 index c942c7f..0000000 --- a/src/settings/settingsPanel.ts +++ /dev/null @@ -1,330 +0,0 @@ -import * as vscode from 'vscode'; -import { getNonce } from "../utilities/getNonce"; -import { getUri } from "../utilities/getUri"; -import * as fs from 'fs'; -import * as path from 'path'; -import { Disposable, Webview, WebviewPanel, window, Uri, ViewColumn } from "vscode"; -import { gExtensionContext } from '../extension'; -import { ConfigAgent, WorkspaceConfig, WorkspaceConfigErrors } from '../configuration'; -import { askReloadFiles } from '../ui/messages'; -import { isMcpServerRunning } from '../mcp/mcpServer'; - - -function deepCopy(obj: any) { - return JSON.parse(JSON.stringify(obj)); -} - -/** - * This class manages the state and behavior of HelloWorld webview panels. - * - * It contains all the data and methods for: - * - * - Creating and rendering HelloWorld webview panels - * - Properly cleaning up and disposing of webview resources when the panel is closed - * - Setting the HTML (and by proxy CSS/JavaScript) content of the webview panel - * - Setting message listeners so data can be passed between the webview and extension - */ -export class SettingsPanel { - public static currentPanel: SettingsPanel | undefined; - private readonly _panel: WebviewPanel; - private _disposables: Disposable[] = []; - private configAgent: ConfigAgent|undefined; - - private addConfigRequested = new vscode.EventEmitter(); - private _configValuesChanged = new vscode.EventEmitter(); - - public get configValuesChanged(): vscode.Event { - return this._configValuesChanged.event; - } - - initialized: boolean = false; - settingsPanelActivated: any; - - /** - * The HelloWorldPanel class private constructor (called only from the render method). - * - * @param panel A reference to the webview panel - * @param extensionUri The URI of the directory containing the extension - */ - private constructor(panel: WebviewPanel, extensionUri: Uri) { - this._panel = panel; - - // Set an event listener to listen for when the panel is disposed (i.e. when the user closes - // the panel or when the panel is closed programmatically) - this._panel.onDidDispose(() => this.dispose(), null, this._disposables); - - // Set the HTML content for the webview panel - this._panel.webview.html = this._getWebviewContent(this._panel.webview, extensionUri); - - // Set an event listener to listen for messages passed from the webview context - this._setWebviewMessageListener(this._panel.webview); - } - - /** - * Renders the current webview panel if it exists otherwise a new webview panel - * will be created and displayed. - * - * @param extensionUri The URI of the directory containing the extension. - */ - public static render(extensionUri: Uri, configAgent:ConfigAgent) { - if (SettingsPanel.currentPanel) { - // If the webview panel already exists reveal it - SettingsPanel.currentPanel._panel.reveal(vscode.ViewColumn.One); - } else { - // If a webview panel does not already exist create and show a new one - const panel = window.createWebviewPanel( - // Panel view type - "showHelloWorld", - // Panel title - "EDK2 Configuration", - // The editor column the panel should be displayed in - vscode.ViewColumn.One, - // Extra panel configurations - { - enableCommandUris:true, - // Enable JavaScript in the webview - enableScripts: true, - // Restrict the webview to only load resources from the `out` directory - localResourceRoots: [Uri.joinPath(extensionUri, "out")], - } - ); - - SettingsPanel.currentPanel = new SettingsPanel(panel, extensionUri); - SettingsPanel.currentPanel.configAgent = configAgent; - SettingsPanel.currentPanel.configValuesChanged(() => configAgent.saveConfigurationUI()); - - } - } - - /** - * Cleans up and disposes of webview resources when the webview panel is closed. - */ - public dispose() { - SettingsPanel.currentPanel = undefined; - - // Dispose of the current webview panel - this._panel.dispose(); - - // Dispose of all disposables (i.e. commands) associated with the current webview panel - while (this._disposables.length) { - const disposable = this._disposables.pop(); - if (disposable) { - disposable.dispose(); - } - } - } - - /** - * Defines and returns the HTML that should be rendered within the webview panel. - * - * @remarks This is also the place where *references* to CSS and JavaScript files - * are created and inserted into the webview HTML. - * - * @param webview A reference to the extension webview - * @param extensionUri The URI of the directory containing the extension - * @returns A template string literal containing the HTML that should be - * rendered within the webview panel - */ - private _getWebviewContent(webview: vscode.Webview, extensionUri: Uri) { - - let content = fs.readFileSync(getUri(webview, extensionUri, ["src", "settings", "settings.html"]).fsPath).toString(); - content = content.replace( - /{{nonce}}/g, - getNonce()); - - const settingsJsUri: vscode.Uri = this._panel.webview.asWebviewUri(getUri(webview, extensionUri, ["out", "settings", "settings.js"])); - content = content.replace( - /{{settings_js_uri}}/g, - settingsJsUri.toString()); - - return content; - } - - - private onMessageReceived(message: any): void { - if (message === null || message === undefined) { - return; - } - switch (message.command) { - case 'change': - this.updateConfig(message); - break; - case 'configSelect': - this.configSelect(message.index); - break; - case 'addConfig': - this.addConfig(message.name); - break; - case 'knownCompilerSelect': - this.knownCompilerSelect(); - break; - case "initialized": - this.initialized = true; - this.initilizePanel(); - break; - case 'selectDscFile': - this.selectDscFile(); - break; - case 'selectPackagePath': - this.selectPackagePath(); - break; - case 'toggleMcp': - this.toggleMcpServer(); - break; - case 'autoConfigureMcp': - this.autoConfigureMcp(); - break; - case 'changeMcpPort': - this.changeMcpPort(message.port); - break; - } - - - } - - initilizePanel() { - SettingsPanel.currentPanel!.updateWebview(this.configAgent!.getWorkspaceConfig(), this.configAgent!.getWorkspaceErrors()); - const port = vscode.workspace.getConfiguration('edk2code').get('mcpServerPort', 3100); - void this._panel.webview.postMessage({ command: 'mcpStatus', running: isMcpServerRunning(), port }); - } - - updateConfig(message: any) { - let configData = message.config; - let config:any = {}; - for (const key in configData) { - let data = configData[key].split("\n").map((x:string)=>{return x.trim();}); - config[key] = data; - } - SettingsPanel.currentPanel?.configAgent?.writeWorkspaceConfig(config); - - askReloadFiles(); - } - configSelect(index: any) { - throw new Error('Method not implemented.'); - } - knownCompilerSelect() { - throw new Error('Method not implemented.'); - } - - private addConfig(name: string): void { - this.addConfigRequested.fire(name); - } - - private async selectDscFile(): Promise { - const workspaceFolders = vscode.workspace.workspaceFolders; - const defaultUri = workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0].uri : undefined; - const result = await vscode.window.showOpenDialog({ - canSelectMany: false, - openLabel: "Select DSC file", - defaultUri: defaultUri, - filters: { "DSC Files": ["dsc"] } - }); - if (result && result.length > 0 && workspaceFolders && workspaceFolders.length > 0) { - const relativePath = path.relative(workspaceFolders[0].uri.fsPath, result[0].fsPath).replace(/\\/g, '/'); - void this._panel.webview.postMessage({ command: 'addDscFile', path: relativePath }); - } - } - - private async selectPackagePath(): Promise { - const workspaceFolders = vscode.workspace.workspaceFolders; - const defaultUri = workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0].uri : undefined; - const result = await vscode.window.showOpenDialog({ - canSelectMany: false, - canSelectFolders: true, - canSelectFiles: false, - openLabel: "Select package path", - defaultUri: defaultUri, - }); - if (result && result.length > 0 && workspaceFolders && workspaceFolders.length > 0) { - const relativePath = path.relative(workspaceFolders[0].uri.fsPath, result[0].fsPath).replace(/\\/g, '/'); - void this._panel.webview.postMessage({ command: 'addPackagePath', path: relativePath }); - } - } - - private async toggleMcpServer(): Promise { - if (isMcpServerRunning()) { - await vscode.commands.executeCommand('edk2code.stopMcpServer'); - } else { - await vscode.commands.executeCommand('edk2code.startMcpServer'); - } - const port = vscode.workspace.getConfiguration('edk2code').get('mcpServerPort', 3100); - void this._panel.webview.postMessage({ command: 'mcpStatus', running: isMcpServerRunning(), port }); - } - - private async changeMcpPort(port: number): Promise { - await vscode.workspace.getConfiguration('edk2code').update('mcpServerPort', port, vscode.ConfigurationTarget.Workspace); - } - - private async autoConfigureMcp(): Promise { - const workspaceFolders = vscode.workspace.workspaceFolders; - if (!workspaceFolders || workspaceFolders.length === 0) { - void this._panel.webview.postMessage({ command: 'mcpConfigResult', message: 'No workspace folder found.' }); - return; - } - const vscodePath = path.join(workspaceFolders[0].uri.fsPath, '.vscode'); - const mcpConfigPath = path.join(vscodePath, 'mcp.json'); - const port = vscode.workspace.getConfiguration('edk2code').get('mcpServerPort', 3100); - const expectedUrl = `http://localhost:${port}/sse`; - - if (fs.existsSync(mcpConfigPath)) { - try { - const existing = JSON.parse(fs.readFileSync(mcpConfigPath, 'utf-8')); - const serverEntry = existing?.servers?.edk2code; - if (serverEntry && serverEntry.url === expectedUrl) { - void this._panel.webview.postMessage({ command: 'mcpConfigResult', message: 'edk2code MCP already configured correctly.' }); - return; - } - // Add or update the edk2code entry - if (!existing.servers) { - existing.servers = {}; - } - existing.servers.edk2code = { type: "sse", url: expectedUrl }; - fs.writeFileSync(mcpConfigPath, JSON.stringify(existing, null, 4), 'utf-8'); - void this._panel.webview.postMessage({ command: 'mcpConfigResult', message: 'Updated edk2code entry in .vscode/mcp.json' }); - } catch { - // File exists but is not valid JSON, overwrite - const mcpConfig = { servers: { edk2code: { type: "sse", url: expectedUrl } } }; - fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 4), 'utf-8'); - void this._panel.webview.postMessage({ command: 'mcpConfigResult', message: 'Replaced invalid .vscode/mcp.json' }); - } - return; - } - - const mcpConfig = { - servers: { - "edk2code": { - "type": "sse", - "url": expectedUrl - } - } - }; - - if (!fs.existsSync(vscodePath)) { - fs.mkdirSync(vscodePath, { recursive: true }); - } - fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 4), 'utf-8'); - void this._panel.webview.postMessage({ command: 'mcpConfigResult', message: 'Created .vscode/mcp.json' }); - } - - - /** - * Sets up an event listener to listen for messages passed from the webview context and - * executes code based on the message that is received. - * - * @param webview A reference to the extension webview - */ - private _setWebviewMessageListener(webview: vscode.Webview) { - webview.onDidReceiveMessage(this.onMessageReceived, this); - } - - - updateWebview(data:WorkspaceConfig, errors:WorkspaceConfigErrors|null): void { - let configValues = deepCopy(data); // Copy configuration values - if (this._panel && this.initialized) { - void this._panel.webview.postMessage({ command: 'updateConfig', config: configValues }); - if (errors !== null) { - void this._panel.webview.postMessage({ command: 'updateErrors', errors: errors }); - } - } - } -} \ No newline at end of file diff --git a/src/statusBar.ts b/src/statusBar.ts deleted file mode 100644 index bd7c84c..0000000 --- a/src/statusBar.ts +++ /dev/null @@ -1,72 +0,0 @@ -import * as vscode from 'vscode'; -import { gExtensionContext } from './extension'; -export var myStatusBarItem: vscode.StatusBarItem; - -var helpUrl:string = ""; -var textStack:string[] = []; - -export function init(context:vscode.ExtensionContext){ - // create a new status bar item that we can now manage - myStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 1); - - const myCommandId = 'edk2code.statusCmd'; - - gExtensionContext.subscriptions.push(vscode.commands.registerCommand(myCommandId, async () => { - await vscode.env.openExternal(vscode.Uri.parse( - helpUrl)); - - })); - myStatusBarItem.command = myCommandId; - context.subscriptions.push(myStatusBarItem); - setText("Started"); -} - -export function setToolTip(text:string){ - myStatusBarItem.tooltip = text; -} - -export function setHelpUrl(url:string ){ - helpUrl = url; -} - -export function setInfo(text:string){ - myStatusBarItem.tooltip = text; -} - - -export function pushText(text:string){ - textStack.push(myStatusBarItem.text); - myStatusBarItem.text = `EDK2: ${text}`; - myStatusBarItem.show(); - myStatusBarItem.tooltip = ""; -} - -export function popText(){ - let text = textStack.pop(); - myStatusBarItem.text = text? text:"EDK2Code"; - myStatusBarItem.show(); - myStatusBarItem.tooltip = ""; -} - -export function setText(text: string): void { - textStack = []; - myStatusBarItem.text = `EDK2: ${text}`; - myStatusBarItem.show(); - myStatusBarItem.tooltip = ""; -} - - -export function setColor(color:string){ - myStatusBarItem.backgroundColor = new vscode.ThemeColor(color); -} - -export function setWorking(){ - if(!myStatusBarItem.text.startsWith("$(sync~spin)")){ - myStatusBarItem.text = `$(sync~spin) ${myStatusBarItem.text}`; - } - -} - -export function clearWorking(){ - myStatusBarItem.text = myStatusBarItem.text.replace("$(sync~spin) ", ""); -} \ No newline at end of file diff --git a/src/symbols/README.md b/src/symbols/README.md deleted file mode 100644 index 3cc1290..0000000 --- a/src/symbols/README.md +++ /dev/null @@ -1,191 +0,0 @@ -# Symbols - -This folder contains the symbol type system used by the EDK II parser. Each language (DSC, INF, DEC, FDF, ASL, VFR) has its own symbol file, plus shared infrastructure. - -## File Overview - -| File | Purpose | -|---|---| -| `symbolsType.ts` | Enum of all symbol types + string mapping | -| `edkSymbols.ts` | Abstract base class `EdkSymbol` | -| `symbolFactory.ts` | Factory that instantiates the correct symbol class from a type | -| `dscSymbols.ts` | DSC-specific symbol classes | -| `infSymbols.ts` | INF-specific symbol classes | -| `decSymbols.ts` | DEC-specific symbol classes | -| `fdfSymbols.ts` | FDF-specific symbol classes | -| `aslSymbols.ts` | ASL-specific symbol classes | -| `vfrSymbols.ts` | VFR-specific symbol classes | -| `commonSymbols.ts` | Shared symbol classes (conditions, unknown) | - ---- - -## How to Add a New Symbol Type - -Adding a new symbol requires changes in **four places**. The example below follows the addition of `dscComponentSubSection` and `dscBuildOption` for DSC component scoped sub-elements (``, ``, ``). - -### 1. Add the type to `symbolsType.ts` - -Add the new enum value to `Edk2SymbolType` and a corresponding entry in `typeToStr`: - -```typescript -// symbolsType.ts -export enum Edk2SymbolType { - // ... - dscSection, - dscComponentSubSection, // <-- new - dscPcdDefinition, - dscBuildOption, // <-- new - // ... -} - -export var typeToStr: Map = new Map([ - // ... - [Edk2SymbolType.dscComponentSubSection, "dscComponentSubSection"], - [Edk2SymbolType.dscBuildOption, "dscBuildOption"], - // ... -]); -``` - -### 2. Create the symbol class in the appropriate `*Symbols.ts` file - -Extend `EdkSymbol` and set at minimum `type` and `kind`. Implement `onDefinition`, `onCompletion`, etc. if the symbol needs navigation or hover support. - -```typescript -// dscSymbols.ts -export class EdkSymbolDscComponentSubSection extends EdkSymbol { - type = Edk2SymbolType.dscComponentSubSection; - kind = vscode.SymbolKind.Namespace; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolDscBuildOption extends EdkSymbol { - type = Edk2SymbolType.dscBuildOption; - kind = vscode.SymbolKind.Property; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -``` - -Optionally override `nameRegex` (defined on the base `EdkSymbol`) to extract a cleaner display name from the raw text line: - -```typescript -// Example from EdkSymbolDscModuleDefinition -protected get nameRegex(): RegExp { return /^\s*([\w/.\\-]+\.inf)/i; } -``` - -When `nameRegex` is set, the constructor uses the first capture group (or the full match) as `this.name` instead of the raw text line. - -### 3. Register the type in `symbolFactory.ts` - -Import the new class and add a `case` to `produceSymbol()`: - -```typescript -// symbolFactory.ts -import { /* existing */, EdkSymbolDscComponentSubSection, EdkSymbolDscBuildOption } from "./dscSymbols"; - -produceSymbol(type: Edk2SymbolType, textLine: string, location: vscode.Location, parser: DocumentParser) { - switch (type) { - // ... - case Edk2SymbolType.dscComponentSubSection: - return new EdkSymbolDscComponentSubSection(textLine, location, true, true, parser); - case Edk2SymbolType.dscBuildOption: - return new EdkSymbolDscBuildOption(textLine, location, true, true, parser); - // ... - } -} -``` - -### 4. Add a `BlockParser` in the relevant parser file - -In `src/edkParser/`, create a `BlockParser` subclass that sets `type` to the new enum value and define `tag` / `end` / `context` as needed. Then add it to the `context` array of the parent block. - -```typescript -// dscParser.ts -class BlockBuildOption extends BlockParser { - name = "BuildOption"; - tag = /^[\w\*\:\|]+\s*=\s*.*/gi; - start = undefined; - end = undefined; - type = Edk2SymbolType.dscBuildOption; - visible: boolean = true; -} - -class BlockComponentSubBuildOptions extends BlockParser { - name = "ComponentBuildOptions"; - tag = /^<\s*BuildOptions\s*>/gi; - start = undefined; - end = /(^<)|(^\})/gi; - type = Edk2SymbolType.dscComponentSubSection; - visible: boolean = true; - context: BlockParser[] = [ - new BlockBuildOption(), - new BlockIncludes(), - ]; -} - -// Wire into the parent block's context: -class BlockComponentInf extends BlockParser { - // ... - context: BlockParser[] = [ - new BlockComponentSubBuildOptions(), - // ... - ]; -} -``` - -If the new type should also appear as a root-level fallback (so lines are captured even when they appear outside any section), register an additional `isRoot = true` instance at the end of `DscParser.blockParsers`: - -```typescript -blockParsers: BlockParser[] = [ - new BlockBuildOptionsSection(), // normal section block - // ... - new BlockBuildOption(true), // isRoot fallback -]; -``` - -### 5. Register the type in `WorkspaceTreeProvider.ts` - -The workspace tree view (`src/workspaceTree/WorkspaceTreeProvider.ts`) uses `DSC_FILTER_TYPES` to control which symbol types are rendered. Any new type that should appear in the tree **must** be added here — both for top-level rendering and for collapsible-state detection on parent nodes. - -```typescript -// WorkspaceTreeProvider.ts -export const DSC_FILTER_TYPES: { type: Edk2SymbolType; label: string; description: string }[] = [ - // ... - { type: Edk2SymbolType.dscBuildOptionsSection, label: 'Build options', description: 'dscBuildOptionsSection' }, - { type: Edk2SymbolType.dscBuildOption, label: 'Build option entries', description: 'dscBuildOption' }, - // ... -]; -``` - -This array serves three roles: -1. **Root filter** — only symbols whose type is in this set are shown at the workspace root level. -2. **Child filter** — `getChildren()` uses it to filter children of every tree node. -3. **Collapsible state** — `DocumentSymbolItem` counts `visibleChildren` against this set to decide whether a node should be expandable. - -Omitting a type from `DSC_FILTER_TYPES` silently hides the symbol and all its children in the tree, even if parsing logs show "Added symbol" correctly. - ---- - -## `EdkSymbol` base class - -All symbol classes extend `EdkSymbol` (defined in `edkSymbols.ts`), which itself extends `vscode.DocumentSymbol`. Key members: - -| Member | Description | -|---|---| -| `type` | The `Edk2SymbolType` enum value | -| `kind` | The `vscode.SymbolKind` used for the outline/breadcrumb icon | -| `textLine` | The raw source line (with defines resolved via `parser.defines`) | -| `location` | `vscode.Location` (URI + range) | -| `sectionProperties` | Inherited from the parent symbol's section context | -| `nameRegex` | Optional getter; when set, extracts the symbol's display name from `textLine` | -| `onDefinition` | Async function returning locations for go-to-definition | -| `onCompletion` | Async function returning completion items | -| `onHover` | Async function returning hover content | -| `onDeclaration` | Async function returning declaration locations | diff --git a/src/symbols/aslSymbols.ts b/src/symbols/aslSymbols.ts deleted file mode 100644 index d70256a..0000000 --- a/src/symbols/aslSymbols.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { SymbolKind, Location, SymbolTag, Range, DocumentSymbol } from "vscode"; -import { Edk2SymbolType } from './symbolsType'; -import * as vscode from 'vscode'; -import { gEdkWorkspaces, gPathFind } from "../extension"; -import { split, trimSpaces } from "../utils"; -import { WorkspaceDefinitions } from "../index/definitions"; -import { DocumentParser } from "../edkParser/languageParser"; -import { EdkSymbol } from "./edkSymbols"; - -export class EdkSymbolAslDefinitionBlock extends EdkSymbol { - - type = Edk2SymbolType.aslDefinitionBlock; - kind = vscode.SymbolKind.Package; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolAslExternal extends EdkSymbol { - - type = Edk2SymbolType.aslExternal; - kind = vscode.SymbolKind.Interface; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolAslScope extends EdkSymbol { - - type = Edk2SymbolType.aslScope; - kind = vscode.SymbolKind.Module; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolAslDevice extends EdkSymbol { - - type = Edk2SymbolType.aslDevice; - kind = vscode.SymbolKind.Constant; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolAslName extends EdkSymbol { - - type = Edk2SymbolType.aslName; - kind = vscode.SymbolKind.String; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolAslMethod extends EdkSymbol { - - type = Edk2SymbolType.aslMethod; - kind = vscode.SymbolKind.Method; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolAslField extends EdkSymbol { - - type = Edk2SymbolType.aslField; - kind = vscode.SymbolKind.String; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolAslOperationRegion extends EdkSymbol { - - type = Edk2SymbolType.aslOpRegion; - kind = vscode.SymbolKind.Enum; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} \ No newline at end of file diff --git a/src/symbols/commonSymbols.ts b/src/symbols/commonSymbols.ts deleted file mode 100644 index 265bcdb..0000000 --- a/src/symbols/commonSymbols.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { EdkSymbol } from "./edkSymbols"; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import * as vscode from 'vscode'; - - -export class EdkSymbolCondition extends EdkSymbol{ - type = Edk2SymbolType.condition; - kind = vscode.SymbolKind.Event; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolUnknown extends EdkSymbol { - type = Edk2SymbolType.unknown; - kind = vscode.SymbolKind.String; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} \ No newline at end of file diff --git a/src/symbols/decSymbols.ts b/src/symbols/decSymbols.ts deleted file mode 100644 index 746cfd4..0000000 --- a/src/symbols/decSymbols.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { EdkSymbol } from "./edkSymbols"; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import * as vscode from 'vscode'; -import { split } from "../utils"; -import path = require("path"); - - - -export class EdkSymbolDecSection extends EdkSymbol { - type = Edk2SymbolType.decSection; - kind = vscode.SymbolKind.Class; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolDecDefine extends EdkSymbol { - type = Edk2SymbolType.decDefine; - kind = vscode.SymbolKind.Constant; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolDecLibrary extends EdkSymbol { - type = Edk2SymbolType.decLibrary; - kind = vscode.SymbolKind.Module; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolDecPackage extends EdkSymbol { - type = Edk2SymbolType.decPackage; - kind = vscode.SymbolKind.Package; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolDecPpi extends EdkSymbol { - type = Edk2SymbolType.decPpi; - kind = vscode.SymbolKind.Event; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; - - async getKey(){ - let key = split(this.textLine, "=",2)[0].trim(); - return key; - } -} -export class EdkSymbolDecProtocol extends EdkSymbol { - type = Edk2SymbolType.decProtocol; - kind = vscode.SymbolKind.Event; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; - - async getKey(){ - let key = split(this.textLine, "=",2)[0].trim(); - return key; - } -} -export class EdkSymbolDecPcd extends EdkSymbol { - type = Edk2SymbolType.decPcd; - kind = vscode.SymbolKind.String; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; - async getKey(){ - let key = split(this.textLine, "|",2)[0].trim(); - return key; - } -} -export class EdkSymbolDecGuid extends EdkSymbol { - type = Edk2SymbolType.decGuid; - kind = vscode.SymbolKind.Number; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; - - async getKey(){ - let key = split(this.textLine, "=",2)[0].trim(); - return key; - } -} -export class EdkSymbolDecIncludes extends EdkSymbol { - type = Edk2SymbolType.decInclude; - kind = vscode.SymbolKind.File; - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; - - async getKey(){ - let key = this.textLine.trim(); - return path.join(path.dirname(this.location.uri.fsPath),key); - } -} \ No newline at end of file diff --git a/src/symbols/dscSymbols.ts b/src/symbols/dscSymbols.ts deleted file mode 100644 index 852497d..0000000 --- a/src/symbols/dscSymbols.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { SymbolKind, Location, SymbolTag, Range, DocumentSymbol } from "vscode"; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import * as vscode from 'vscode'; -import { gDebugLog, gEdkWorkspaces, gPathFind } from "../extension"; -import { split, trimSpaces } from "../utils"; -import { WorkspaceDefinitions } from "../index/definitions"; -import { DocumentParser } from "../edkParser/languageParser"; -import { EdkSymbol } from "./edkSymbols"; -import { REGEX_LIBRARY_PATH } from "../edkParser/commonParser"; -import { DebugLog } from "../debugLog"; - - -export class EdkSymbolDscSection extends EdkSymbol { - type = Edk2SymbolType.dscSection; - kind = vscode.SymbolKind.Class; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - - -export class EdkSymbolDscDefine extends EdkSymbol{ - type = Edk2SymbolType.dscDefine; - kind = vscode.SymbolKind.Constant; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; - - - protected get nameRegex(): RegExp { return /define\s+(\w+).*=.*/i; } - protected get descriptionRegex(): RegExp { return /define\s+\w+\s*=\s*(.*)/i; } - - - - async getKey() { - let key = this.textLine.replace(/define/gi, "").trim(); - key = split(key, "=", 2)[0].trim(); - key = await gEdkWorkspaces.replaceDefines(this.location.uri, key);; - return key; - } - - async getValue(){ - let value = split(this.textLine, "=", 2)[1].trim(); - value = await gEdkWorkspaces.replaceDefines(this.location.uri, value); - return value; - } -} - - -export class EdkSymbolDscLibraryDefinition extends EdkSymbol{ - type = Edk2SymbolType.dscLibraryDefinition; - kind = vscode.SymbolKind.Field; - - protected get descriptionRegex(): RegExp { return /.*\|(.*)/i; } - protected get nameRegex(): RegExp { return /(.*)\|.*/i; } - - onCompletion: undefined; - onDefinition = async (parser:DocumentParser)=>{ - let path = this.textLine.replace(/.*?\|\s*/gi, ""); - path = await gEdkWorkspaces.replaceDefines(this.location.uri, path); - return await gPathFind.findPath(path); - }; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolDscPcdDefinition extends EdkSymbol{ - type = Edk2SymbolType.dscPcdDefinition; - kind = vscode.SymbolKind.String; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolDscInclude extends EdkSymbol{ - type = Edk2SymbolType.dscInclude; - kind = vscode.SymbolKind.File; - - onCompletion: undefined; - onDefinition = async (parser:DocumentParser)=>{ - let path = await this.getValue(); - return await gPathFind.findPath(path, parser.document.uri.fsPath); - }; - onHover: undefined; - onDeclaration: undefined; - - async getValue(){ - let value = this.textLine.replace(/!include/gi, "").trim(); - value = await gEdkWorkspaces.replaceDefines(this.location.uri, value); - return value; - } -} - - -export class EdkSymbolDscLine extends EdkSymbol{ - type = Edk2SymbolType.dscLine; - kind = vscode.SymbolKind.String; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolDscBuildOptionsSection extends EdkSymbol { - type = Edk2SymbolType.dscBuildOptionsSection; - kind = vscode.SymbolKind.Class; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolDscComponentSubSection extends EdkSymbol { - type = Edk2SymbolType.dscComponentSubSection; - kind = vscode.SymbolKind.Namespace; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolDscBuildOption extends EdkSymbol { - type = Edk2SymbolType.dscBuildOption; - kind = vscode.SymbolKind.Property; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolDscModuleDefinition extends EdkSymbol{ - type = Edk2SymbolType.dscModuleDefinition; - kind = vscode.SymbolKind.Method; - - protected get nameRegex(): RegExp { return /.*?\.inf/i; } - - onCompletion: undefined; - onDefinition = async ()=>{ - let path = this.textLine.replace(/\s*\{.*/, ""); - path = await gEdkWorkspaces.replaceDefines(this.location.uri, path); - return await gPathFind.findPath(path); - }; - - onHover: undefined; - onDeclaration: undefined; -} - diff --git a/src/symbols/edkSymbols.ts b/src/symbols/edkSymbols.ts deleted file mode 100644 index 4398bcf..0000000 --- a/src/symbols/edkSymbols.ts +++ /dev/null @@ -1,214 +0,0 @@ -import * as vscode from 'vscode'; -import { gDebugLog } from '../extension'; -import { Edk2SymbolType, typeToStr } from './symbolsType'; -import { DocumentParser } from '../edkParser/languageParser'; -import { SectionProperties } from '../index/edkWorkspace'; -import { getParserForDocument } from '../edkParser/parserFactory'; -import path = require('path'); -import { debuglog } from 'util'; -import { log } from 'console'; - -let decSymbolCache = new Map(); - - -export abstract class EdkSymbol extends vscode.DocumentSymbol { - type: Edk2SymbolType = Edk2SymbolType.unknown; - - // Events - abstract onCompletion: undefined|Function; - abstract onDefinition: undefined|Function; - abstract onHover: undefined|Function; - abstract onDeclaration: undefined|Function; - - location: vscode.Location; - - enabled: boolean = true; - visible: boolean = true; - - sectionProperties: SectionProperties; - parent: EdkSymbol | undefined = undefined; - - guid:string = ""; - parser:DocumentParser; - - /** Override in subclasses to extract a specific portion of the text line as the symbol name. */ - protected get nameRegex(): RegExp | undefined { return undefined; } - - /** Override in subclasses to extract a description (detail) from the text line. */ - protected get descriptionRegex(): RegExp | undefined { return undefined; } - - - - - protected _textLine: string; - public get textLine(): string { - return this.parser.defines.replaceDefines(this._textLine); - } - public set textLine(value: string) { - this._textLine = value; - } - - updateRange(range:vscode.Range){ - this.location.range = range; - this.range = range; - // Trim selectionRange to the uncommented, non-whitespace content on the first line. - // _textLine is already the trimmed, comment-free text from parsing. - const lineStart = range.start.line; - const content = this._textLine; - if (content.length > 0 && lineStart < this.parser.document.lineCount) { - const rawLine = this.parser.document.lineAt(lineStart).text; - const idx = rawLine.indexOf(content); - if (idx >= 0) { - this.selectionRange = new vscode.Range( - lineStart, idx, - lineStart, idx + content.length - ); - return; - } - } - this.selectionRange = range; - } - - - - public constructor(textLine: string, location: vscode.Location, enabled: boolean, visible: boolean, parser:DocumentParser) { - super(textLine, "", vscode.SymbolKind.Null, - location.range, - location.range); - - // Debug - // this.detail = this.constructor.toString().match(/\w+/g)![1]; - - this.enabled = enabled; - this.visible = visible; - this.location = location; - this._textLine = textLine; - this.parser = parser; - const regex = this.nameRegex; - if (regex) { - const match = textLine.match(regex); - this.name = match ? (match[1] ?? match[0]).trim() : textLine.trim(); - } else { - this.name = textLine.replaceAll(/\s+/gi, " "); - } - - const descRegex = this.descriptionRegex; - if (descRegex) { - const descMatch = textLine.match(descRegex); - this.detail = descMatch ? (descMatch[1] ?? descMatch[0]).trim() : ''; - } - - let parent = parser.symbolStack[parser.symbolStack.length - 1]; - this.sectionProperties = new SectionProperties(); - if(parent){ - this.sectionProperties = parent.sectionProperties; - } - gDebugLog.trace(`Symbol Created: ${location.range.start.line}: ${this.toString()}`); - } - - async decCompletion(type:Edk2SymbolType, completionKind:vscode.CompletionItemKind=vscode.CompletionItemKind.File){ - let retData = []; - let decs = this.parser.getSymbolsType(Edk2SymbolType.infPackage); - for (const dec of decs) { - let decTextPath = await dec.getValue(); - let document = await vscode.workspace.openTextDocument(vscode.Uri.file(decTextPath)); - let decParser = await getParserForDocument(document); - if(decParser){ - let decPpis = decParser.getSymbolsType(type); - for (const decPpi of decPpis) { - let decPpiValue = await decPpi.getKey(); - retData.push(new vscode.CompletionItem({label:decPpiValue, detail:" " + path.basename(decPpi.location.uri.fsPath), description:""}, completionKind)); - } - } - } - return retData; - } - - async isInDec(type:Edk2SymbolType){ - let decs = this.parser.getSymbolsType(Edk2SymbolType.infPackage); - const testKey = await this.getKey(); - - - for (const dec of decs) { - let decTextPath = await dec.getValue(); - if(decSymbolCache.has(testKey)){ - let cachedPath = decSymbolCache.get(testKey); - if(cachedPath === decTextPath){ - return true; - } - } - let document = await vscode.workspace.openTextDocument(vscode.Uri.file(decTextPath)); - let decParser = await getParserForDocument(document); - if(decParser){ - let decSymbols = decParser.getSymbolsType(type); - for (const decSymbol of decSymbols) { - - const symbolKey = await decSymbol.getKey(); - decSymbolCache.set(symbolKey, decTextPath); - if(symbolKey === testKey){ - return true; - } - } - } - } - return false; - } - - - toString() { - return `(${this.range.start.line + 1},${this.range.start.character}),(${this.range.end.line + 1},${this.range.end.character})(${this.typeToString()}): ${this.name}`; - } - - - typeToString() { - return typeToStr.get(this.type); - } - - async getValue(){ - // gDebugLog.warning(`getValue not implemented for ${this.type}`); - return this.textLine; - } - - async getKey(){ - // gDebugLog.warning(`getKey not implemented for ${this.type}`); - return this.textLine; - } - - static iconForKind(kind: vscode.SymbolKind): vscode.ThemeIcon { - const map: Partial> = { - [vscode.SymbolKind.File]: { icon: 'symbol-file', color: 'symbolIcon.fileForeground' }, - [vscode.SymbolKind.Module]: { icon: 'symbol-module', color: 'symbolIcon.moduleForeground' }, - [vscode.SymbolKind.Namespace]: { icon: 'symbol-namespace', color: 'symbolIcon.namespaceForeground' }, - [vscode.SymbolKind.Package]: { icon: 'symbol-package', color: 'symbolIcon.packageForeground' }, - [vscode.SymbolKind.Class]: { icon: 'symbol-class', color: 'symbolIcon.classForeground' }, - [vscode.SymbolKind.Method]: { icon: 'symbol-method', color: 'symbolIcon.methodForeground' }, - [vscode.SymbolKind.Property]: { icon: 'symbol-property', color: 'symbolIcon.propertyForeground' }, - [vscode.SymbolKind.Field]: { icon: 'symbol-field', color: 'symbolIcon.fieldForeground' }, - [vscode.SymbolKind.Constructor]: { icon: 'symbol-constructor', color: 'symbolIcon.constructorForeground' }, - [vscode.SymbolKind.Enum]: { icon: 'symbol-enum', color: 'symbolIcon.enumeratorForeground' }, - [vscode.SymbolKind.Interface]: { icon: 'symbol-interface', color: 'symbolIcon.interfaceForeground' }, - [vscode.SymbolKind.Function]: { icon: 'symbol-function', color: 'symbolIcon.functionForeground' }, - [vscode.SymbolKind.Variable]: { icon: 'symbol-variable', color: 'symbolIcon.variableForeground' }, - [vscode.SymbolKind.Constant]: { icon: 'symbol-constant', color: 'symbolIcon.constantForeground' }, - [vscode.SymbolKind.String]: { icon: 'symbol-string', color: 'symbolIcon.stringForeground' }, - [vscode.SymbolKind.Number]: { icon: 'symbol-number', color: 'symbolIcon.numberForeground' }, - [vscode.SymbolKind.Boolean]: { icon: 'symbol-boolean', color: 'symbolIcon.booleanForeground' }, - [vscode.SymbolKind.Array]: { icon: 'symbol-array', color: 'symbolIcon.arrayForeground' }, - [vscode.SymbolKind.Object]: { icon: 'symbol-object', color: 'symbolIcon.objectForeground' }, - [vscode.SymbolKind.Key]: { icon: 'symbol-key', color: 'symbolIcon.keyForeground' }, - [vscode.SymbolKind.Null]: { icon: 'symbol-null', color: 'symbolIcon.nullForeground' }, - [vscode.SymbolKind.EnumMember]: { icon: 'symbol-enum-member', color: 'symbolIcon.enumeratorMemberForeground' }, - [vscode.SymbolKind.Struct]: { icon: 'symbol-struct', color: 'symbolIcon.structForeground' }, - [vscode.SymbolKind.Event]: { icon: 'symbol-event', color: 'symbolIcon.eventForeground' }, - [vscode.SymbolKind.Operator]: { icon: 'symbol-operator', color: 'symbolIcon.operatorForeground' }, - [vscode.SymbolKind.TypeParameter]: { icon: 'symbol-type-parameter', color: 'symbolIcon.typeParameterForeground' }, - }; - const entry = map[kind]; - if (entry) { - return new vscode.ThemeIcon(entry.icon, new vscode.ThemeColor(entry.color)); - } - return new vscode.ThemeIcon('symbol-misc'); - } - -} - diff --git a/src/symbols/fdfSymbols.ts b/src/symbols/fdfSymbols.ts deleted file mode 100644 index 66e5647..0000000 --- a/src/symbols/fdfSymbols.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { gEdkWorkspaces, gPathFind } from "../extension"; -import { EdkSymbol } from "./edkSymbols"; -import * as vscode from 'vscode'; -import { Edk2SymbolType } from "./symbolsType"; -import { WorkspaceDefinitions } from "../index/definitions"; -import { DocumentParser } from "../edkParser/languageParser"; -import * as path from 'path'; - -export class EdkSymbolDscSection extends EdkSymbol { - type = Edk2SymbolType.dscSection; - kind = vscode.SymbolKind.Class; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolFdfSection extends EdkSymbol { - - type = Edk2SymbolType.fdfSection; - kind = vscode.SymbolKind.Class; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolFdfInf extends EdkSymbol { - - type = Edk2SymbolType.fdfInf; - kind = vscode.SymbolKind.Method; - - onCompletion: undefined; - - onDefinition = async (parser:DocumentParser)=>{ - let pathValue = await this.getValue(); - let relPath = path.dirname(parser.document.uri.fsPath); - return await gPathFind.findPath(pathValue, relPath); - }; - - async getValue(){ - let value = this.textLine.replace(/\INF\s+/, "").trim(); - - value = await gEdkWorkspaces.replaceDefines(this.location.uri, value); - return value; - } - - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolFdfDefinition extends EdkSymbol { - - type = Edk2SymbolType.fdfDefinition; - kind = vscode.SymbolKind.Constant; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolFdfFile extends EdkSymbol { - - type = Edk2SymbolType.fdfFile; - kind = vscode.SymbolKind.File; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolFdfInclude extends EdkSymbol { - - type = Edk2SymbolType.fdfInclude; - kind = vscode.SymbolKind.File; - - onCompletion: undefined; - - onDefinition = async (parser:DocumentParser)=>{ - let pathValue = await this.getValue(); - let relPath = path.dirname(parser.document.uri.fsPath); - return await gPathFind.findPath(pathValue, relPath); - }; - - async getValue(){ - let value = this.textLine.replace(/!include/gi, "").trim(); - value = await gEdkWorkspaces.replaceDefines(this.location.uri, value); - return value; - } - - onHover: undefined; - onDeclaration: undefined; -} \ No newline at end of file diff --git a/src/symbols/infSymbols.ts b/src/symbols/infSymbols.ts deleted file mode 100644 index f813dde..0000000 --- a/src/symbols/infSymbols.ts +++ /dev/null @@ -1,569 +0,0 @@ -import { gConfigAgent, gCscope, gDebugLog, gEdkWorkspaces, gPathFind, gWorkspacePath } from "../extension"; -import path = require('path'); -import { EdkSymbol } from "./edkSymbols"; -import * as vscode from 'vscode'; -import { rgSearch, rgSearchText } from "../rg"; -import { Edk2SymbolType } from "./symbolsType"; -import { isFileEdkLibrary, listFiles, listFilesRecursive, openTextDocument, split } from "../utils"; -import { InfDsc } from "../index/edkWorkspace"; -import { DocumentParser } from "../edkParser/languageParser"; -import * as fs from 'fs'; -import { getParserForDocument } from "../edkParser/parserFactory"; -import { REGEX_INF_SECTION } from "../edkParser/commonParser"; - - - -export class InfSection extends EdkSymbol{ - onCompletion: Function | undefined; - onDefinition: Function | undefined; - onHover: Function | undefined; - onDeclaration: Function | undefined; - - public constructor(textLine: string, location: vscode.Location, enabled: boolean, visible: boolean, parser:DocumentParser) { - super(textLine,location, enabled, visible, parser); - textLine = textLine.replace('[','').replace(']','').trim(); - let items = textLine.split(','); - for (const item of items) { - REGEX_INF_SECTION.lastIndex = 0; - let match = REGEX_INF_SECTION.exec(item.trim()); - if(match){ - let sectionType = (match.groups?.['sectionType'] || '').toLowerCase(); - let arch = (match.groups?.['arch'] || 'common').toLowerCase(); - this.sectionProperties.addProperty(sectionType, arch, "Library"); - } - } - - - - - - } -} - -export class EdkSymbolInfSectionLibraries extends InfSection { - - type = Edk2SymbolType.infSectionLibraries; - kind = vscode.SymbolKind.Class; - - - onCompletion = async ()=>{ - return completeLib(this); - }; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolInfSectionSource extends InfSection { - - type = Edk2SymbolType.infSectionSource; - kind = vscode.SymbolKind.Class; - - - onCompletion = async (document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext)=>{ - let text = document.getText(this.location.range); - - let files = await listFilesRecursive(path.dirname(this.location.uri.fsPath)); - let retData = []; - for(const file of files){ - retData.push(new vscode.CompletionItem({label:file.replaceAll("\\","/"), detail:"", description:""}, vscode.CompletionItemKind.File)); - } - return retData; - }; - - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolInfSectionProtocols extends InfSection { - - type = Edk2SymbolType.infSectionProtocols; - kind = vscode.SymbolKind.Class; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decProtocol, vscode.CompletionItemKind.Interface); - }; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - - -export class EdkSymbolInfPpi extends EdkSymbol { - - type = Edk2SymbolType.infPpi; - kind = vscode.SymbolKind.Event; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decPpi, vscode.CompletionItemKind.Interface); - }; - - onDefinition = async (parser:DocumentParser)=>{ - return decDefinition(this,Edk2SymbolType.decPpi); - }; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolInfSectionPpis extends InfSection { - - type = Edk2SymbolType.infSectionPpis; - kind = vscode.SymbolKind.Class; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decPpi, vscode.CompletionItemKind.Interface); - }; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfSectionGuids extends InfSection { - - type = Edk2SymbolType.infSectionGuids; - kind = vscode.SymbolKind.Class; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decGuid, vscode.CompletionItemKind.Constant); - }; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolinfSectionDepex extends InfSection { - - type = Edk2SymbolType.infSectionDepex; - kind = vscode.SymbolKind.Class; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decGuid, vscode.CompletionItemKind.Constant); - }; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolInfSectionPcds extends InfSection { - - type = Edk2SymbolType.infSectionPcds; - kind = vscode.SymbolKind.Class; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decPcd, vscode.CompletionItemKind.Constant); - }; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfSection extends EdkSymbol { - - type = Edk2SymbolType.infSection; - kind = vscode.SymbolKind.Class; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolSectionPackages extends InfSection { - - type = Edk2SymbolType.infSectionPackages; - kind = vscode.SymbolKind.Class; - - onCompletion = async (parser:DocumentParser)=>{ - return completionPackage(); - }; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolInfDefine extends EdkSymbol { - - type = Edk2SymbolType.infDefine; - kind = vscode.SymbolKind.Constant; - - public constructor(textLine: string, location: vscode.Location, enabled: boolean, visible: boolean, parser:DocumentParser) { - super(textLine,location, enabled, visible, parser); - let key = split(this._textLine.replace(/^\s*define\s*/gi,""),"=",2)[0].trim(); - let value = split(this._textLine, "=", 2)[1].trim(); - this.parser.defines.setDefinition(key,value,location); - } - - async getKey() { - let key = split(this.textLine,"=",2)[0].trim(); - return key.replace(/\s*define\s*/gi, ""); - } - - async getValue(){ - let value = split(this.textLine, "=", 2)[1].trim(); - return value; - } - - onCompletion: undefined; - onDefinition = async (parser:DocumentParser)=>{ - - let key = await this.getKey(); - if(["constructor", "destructor", "entry_point"].includes(key.toLowerCase())){ - let sources = parser.getSymbolsType(Edk2SymbolType.infSource); - let p = []; - for (const s of sources) { - p.push(await s.getValue()); - } - let wps = await gEdkWorkspaces.getWorkspace(this.location.uri); - if(wps.length){ - let locations = await gCscope.getDefinitionPositions(await this.getValue()); - if(locations.length){ - return locations; - } - } - - let locations = await rgSearch(await this.getValue(),[],p); - return locations; - - } - - - - }; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfSource extends EdkSymbol { - - type = Edk2SymbolType.infSource; - kind = vscode.SymbolKind.File; - - onCompletion = async (document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext)=>{ - let text = document.getText(this.location.range); - let listDirPath = path.join(path.dirname(this.location.uri.fsPath),text.trim()); - let files = await listFiles(listDirPath); - let retData = []; - for(const file of files){ - const stat = fs.statSync(file); - let icon = vscode.CompletionItemKind.File; - if (stat.isDirectory()) { - icon = vscode.CompletionItemKind.Folder; - } - let relativePath = file.replace(listDirPath,""); - retData.push(new vscode.CompletionItem({label:relativePath.replaceAll("\\","/"), detail:"", description:""}, icon)); - } - return retData; - }; - - onDefinition = async (parser:DocumentParser)=>{ - let filePath = this.textLine.replace(/\s*\|.*/, ""); - let relPath = path.dirname(this.location.uri.fsPath); - return await gPathFind.findPath(filePath, relPath); - }; - onHover: undefined; - onDeclaration: undefined; - - async getValue(){ - - let filePathText = this.textLine.replace(/\s*\|.*/, ""); - let relPath = path.dirname(this.location.uri.fsPath); - let filePath = await gPathFind.findPath(filePathText,relPath); - if(filePath.length){ - return filePath[0].uri.fsPath; - } - return this.textLine; - } -} -export class EdkSymbolInfLibrary extends EdkSymbol { - - type = Edk2SymbolType.infLibrary; - kind = vscode.SymbolKind.Module; - - onCompletion = async ()=>{ - return completeLib(this); - }; - - - - onDefinition = async (parser:DocumentParser)=>{ - let libName = this.textLine.replace(/\s*\|.*/, ""); - - - let wps = await gEdkWorkspaces.getWorkspace(this.location.uri); - if(wps.length){ - - - // Check if this is a library - let isLibrary = await isFileEdkLibrary(this.location.uri); - - if(isLibrary){ - let libDeclarationLocations:vscode.Location[] = []; - for (const wp of wps) { - libDeclarationLocations = libDeclarationLocations.concat(await wp.getLibDefinition(libName)); - } - return libDeclarationLocations; - }else{ - // Modules - let dscLibDeclarations:InfDsc[] = []; - for (const wp of wps) { - dscLibDeclarations = dscLibDeclarations.concat(await wp.getLibDeclarationModule(this.location.uri, libName)); - } - let libDeclarationLocations:vscode.Location[] = []; - for (const declaration of dscLibDeclarations) { - let location = await gPathFind.findPath(declaration.path); - if(location.length){ - libDeclarationLocations.push(location[0]); - } - } - return libDeclarationLocations; - } - - }else{ - let locations = await rgSearch(`--regexp "LIBRARY_CLASS\\s*=\\s*\\b${libName}\\b"`,["*.inf"]); - return locations; - } - - }; - - - onHover: undefined; - - onDeclaration = async ()=>{ - let libName = this.textLine.replace(/\s*\|.*/, ""); - - - let wps = await gEdkWorkspaces.getWorkspace(this.location.uri); - if(wps.length){ - - let isLibrary = await isFileEdkLibrary(this.location.uri); - if(isLibrary){ - // Libraries return all results of libraries used in workspaces - let dscLibDeclarations:InfDsc[] = []; - for (const wp of wps) { - dscLibDeclarations = dscLibDeclarations.concat(await wp.getLibDeclaration(libName)); - } - return dscLibDeclarations.map((x)=>{return x.location;}); - }else{ - - // Libraries return all results of libraries used in workspaces - let dscLibDeclarations:InfDsc[] = []; - for (const wp of wps) { - dscLibDeclarations = dscLibDeclarations.concat(await wp.getLibDeclarationModule(this.location.uri, libName)); - } - return dscLibDeclarations.map((x)=>{return x.location;}); - } - }else{ - let locations = await rgSearch(`--regexp "\\b${libName}\\s*\\|\\b"`,["*.dsc","*.dsc.inc"]); - return locations; - } - }; - - - async getDefinition(parser:DocumentParser){ - let libName = this.textLine.replace(/\s*\|.*/, ""); - let wps = await gEdkWorkspaces.getWorkspace(this.location.uri); - if(wps.length){ - - - // Check if this is a library - let isLibrary = await isFileEdkLibrary(this.location.uri); - - if(isLibrary){ - let libDeclarationLocations:vscode.Location[] = []; - for (const wp of wps) { - libDeclarationLocations = libDeclarationLocations.concat(await wp.getLibDefinition(libName)); - } - return libDeclarationLocations; - }else{ - // Modules - let dscLibDeclarations:InfDsc[] = []; - for (const wp of wps) { - dscLibDeclarations = dscLibDeclarations.concat(await wp.getLibDeclarationModule(this.location.uri, libName)); - } - let libDeclarationLocations:vscode.Location[] = []; - for (const declaration of dscLibDeclarations) { - let location = await gPathFind.findPath(declaration.path); - if(location.length){ - libDeclarationLocations.push(location[0]); - } - } - return libDeclarationLocations; - } - - }else{ - let locations = await rgSearch(`--regexp "LIBRARY_CLASS\\s*=\\s*\\b${libName}\\b"`,["*.inf"]); - return locations; - } - } -} -export class EdkSymbolInfPackage extends EdkSymbol { - - type = Edk2SymbolType.infPackage; - kind = vscode.SymbolKind.Package; - - onCompletion = async (parser:DocumentParser)=>{ - return completionPackage(); - }; - - onDefinition = async (parser:DocumentParser)=>{ - let filePath = this.textLine.replace(/\s*\|.*/, ""); - return await gPathFind.findPath(filePath); - }; - async getValue(){ - let filePath = this.textLine.replace(/\s*\|.*/, ""); - let path = await gPathFind.findPath(filePath); - if(path.length){ - return path[0].uri.fsPath; - } - return ""; - } - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfProtocol extends EdkSymbol { - - type = Edk2SymbolType.infProtocol; - kind = vscode.SymbolKind.Event; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decProtocol, vscode.CompletionItemKind.Interface); - }; - onDefinition = async (parser:DocumentParser)=>{ - return decDefinition(this, Edk2SymbolType.decProtocol); - }; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfPcd extends EdkSymbol { - - type = Edk2SymbolType.infPcd; - kind = vscode.SymbolKind.String; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decPcd, vscode.CompletionItemKind.Constant); - }; - onDefinition = async (parser:DocumentParser)=>{ - return decDefinition(this, Edk2SymbolType.decPcd); - }; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfGuid extends EdkSymbol { - - type = Edk2SymbolType.infGuid; - kind = vscode.SymbolKind.Number; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decGuid, vscode.CompletionItemKind.Constant); - }; - onDefinition = async (parser:DocumentParser)=>{ - return decDefinition(this,Edk2SymbolType.decGuid); - }; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfDepex extends EdkSymbol { - - type = Edk2SymbolType.infDepex; - kind = vscode.SymbolKind.Property; - - onCompletion = async (parser:DocumentParser)=>{ - return this.decCompletion(Edk2SymbolType.decPpi, vscode.CompletionItemKind.Interface); - }; - - onDefinition = async (parser:DocumentParser)=>{ - return decDefinition(this,Edk2SymbolType.decPpi); - }; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfBinary extends EdkSymbol { - - type = Edk2SymbolType.infBinary; - kind = vscode.SymbolKind.Field; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} -export class EdkSymbolInfFunction extends EdkSymbol { - - type = Edk2SymbolType.infFunction; - kind = vscode.SymbolKind.Method; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - - - - -async function decDefinition(thisSymbol:EdkSymbol, type:Edk2SymbolType){ - let thisPpi = await thisSymbol.getKey(); - let decs = thisSymbol.parser.getSymbolsType(Edk2SymbolType.infPackage); - for (const dec of decs) { - let decTextPath = await dec.getValue(); - let document = await openTextDocument(vscode.Uri.file(decTextPath)); - let decParser = await getParserForDocument(document); - if(decParser){ - let decPpis = decParser.getSymbolsType(type); - for (const decPpi of decPpis) { - let decPpiValue = await decPpi.getKey(); - if(decPpiValue === thisPpi){ - return decPpi.location; - } - } - } - } -} - -async function completionPackage(){ - let paths = await vscode.workspace.findFiles(`**\\*.dec`); - let retData = []; - let includePaths = gConfigAgent.getBuildPackagePaths(); - for (const p of includePaths) { - for (const file of paths) { - if(file.fsPath.startsWith(p + path.sep)){ - let completion = file.fsPath.slice(p.length + 1).replaceAll("\\","/"); - retData.push(new vscode.CompletionItem({label:completion, detail:"", description:""}, vscode.CompletionItemKind.File)); - } - } - } - return retData; -} - -async function completeLib(thisSymbol:EdkSymbol) { - let retData = []; - let wps = await gEdkWorkspaces.getWorkspace(thisSymbol.location.uri); - let libPaths: string[] = []; - if(wps.length) { - for(const wp of wps) { - for(const lib of wp.filesLibraries) { - let libNameDsc = lib.text.split("|", 2)[0].trim(); - if(libPaths.includes(libNameDsc)) { - continue; - } - - retData.push(new vscode.CompletionItem({label:libNameDsc, detail: "", description: ""}, vscode.CompletionItemKind.Enum)); - libPaths.push(libNameDsc); - } - } - } else { - let textList = await rgSearchText(`-i --regexp "^\\s*LIBRARY_CLASS\\s*="`, ["*.inf"]); - let libNames: string[] = []; - for(const text of textList) { - // Push libName to return data: - // LIBRARY_CLASS = libName | values - // ^^^^^^^ - let libName = text.split("=", 2)[1].split("|", 2)[0].trim(); - // Skip NULL libraries - if(libName.toLowerCase() === "null"){continue;} - if(!libNames.includes(libName)) { - libNames.push(libName); - retData.push(new vscode.CompletionItem({label:libName, detail: "", description: ""}, vscode.CompletionItemKind.Enum)); - } - } - } - return retData; -} \ No newline at end of file diff --git a/src/symbols/symbolFactory.ts b/src/symbols/symbolFactory.ts deleted file mode 100644 index 8bef072..0000000 --- a/src/symbols/symbolFactory.ts +++ /dev/null @@ -1,193 +0,0 @@ -import * as vscode from 'vscode'; -import { gDebugLog } from "../extension"; - -import { EdkSymbolDscDefine, EdkSymbolDscInclude, EdkSymbolDscLibraryDefinition, EdkSymbolDscLine, EdkSymbolDscModuleDefinition, EdkSymbolDscPcdDefinition, EdkSymbolDscSection, EdkSymbolDscBuildOptionsSection, EdkSymbolDscComponentSubSection, EdkSymbolDscBuildOption } from "./dscSymbols"; -import { EdkSymbolFdfSection, EdkSymbolFdfInf, EdkSymbolFdfDefinition, EdkSymbolFdfFile, EdkSymbolFdfInclude } from './fdfSymbols'; -import { EdkSymbolInfSectionLibraries, EdkSymbolInfSectionProtocols, EdkSymbolInfSectionPpis, EdkSymbolInfSectionGuids, EdkSymbolInfSectionPcds, EdkSymbolInfSection, EdkSymbolInfDefine, EdkSymbolInfSource, EdkSymbolInfLibrary, EdkSymbolInfPackage, EdkSymbolInfPpi, EdkSymbolInfProtocol, EdkSymbolInfPcd, EdkSymbolInfGuid, EdkSymbolInfDepex, EdkSymbolInfBinary, EdkSymbolInfFunction, EdkSymbolInfSectionSource, EdkSymbolSectionPackages, EdkSymbolinfSectionDepex } from './infSymbols'; -import { EdkSymbolDecSection, EdkSymbolDecDefine, EdkSymbolDecLibrary, EdkSymbolDecPackage, EdkSymbolDecPpi, EdkSymbolDecProtocol, EdkSymbolDecPcd, EdkSymbolDecGuid, EdkSymbolDecIncludes } from './decSymbols'; -import { EdkSymbolCondition, EdkSymbolUnknown } from './commonSymbols'; -import { Edk2SymbolType } from './symbolsType'; -import { DocumentParser } from '../edkParser/languageParser'; -import { EdkSymbolVfrDefault, EdkSymbolVfrFormset, EdkSymbolVfrForm, EdkSymbolVfrOneof, EdkSymbolVfrCheckbox, EdkSymbolVfrString, EdkSymbolVfrPassword, EdkSymbolVfrNumeric, EdkSymbolVfrGoto } from './vfrSymbols'; -import { EdkSymbolAslDefinitionBlock, EdkSymbolAslExternal, EdkSymbolAslScope, EdkSymbolAslDevice, EdkSymbolAslName, EdkSymbolAslMethod, EdkSymbolAslField, EdkSymbolAslOperationRegion } from './aslSymbols'; - - - -export class SymbolFactory { - - produceSymbol(type: Edk2SymbolType, textLine: string, location: vscode.Location, parser:DocumentParser) { - - switch (type) { - case Edk2SymbolType.dscSection: - return new EdkSymbolDscSection(textLine, location, true, true, parser); - case Edk2SymbolType.dscBuildOptionsSection: - return new EdkSymbolDscBuildOptionsSection(textLine, location, true, true, parser); - case Edk2SymbolType.dscDefine: - return new EdkSymbolDscDefine(textLine, location, true, true, parser); - case Edk2SymbolType.dscLibraryDefinition: - return new EdkSymbolDscLibraryDefinition(textLine, location, true, true, parser); - case Edk2SymbolType.dscModuleDefinition: - return new EdkSymbolDscModuleDefinition(textLine, location, true, true, parser); - case Edk2SymbolType.dscPcdDefinition: - return new EdkSymbolDscPcdDefinition(textLine, location, true, true, parser); - case Edk2SymbolType.dscInclude: - return new EdkSymbolDscInclude(textLine, location, true, true, parser); - case Edk2SymbolType.dscLine: - return new EdkSymbolDscLine(textLine, location, true, true, parser); - case Edk2SymbolType.dscComponentSubSection: - return new EdkSymbolDscComponentSubSection(textLine, location, true, true, parser); - case Edk2SymbolType.dscBuildOption: - return new EdkSymbolDscBuildOption(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionSource: - return new EdkSymbolInfSectionSource(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionPackages: - return new EdkSymbolSectionPackages(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionLibraries: - return new EdkSymbolInfSectionLibraries(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionProtocols: - return new EdkSymbolInfSectionProtocols(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionPpis: - return new EdkSymbolInfSectionPpis(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionGuids: - return new EdkSymbolInfSectionGuids(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionDepex: - return new EdkSymbolinfSectionDepex(textLine, location, true, true, parser); - case Edk2SymbolType.infSectionPcds: - return new EdkSymbolInfSectionPcds(textLine, location, true, true, parser); - case Edk2SymbolType.infSection: - return new EdkSymbolInfSection(textLine, location, true, true, parser); - case Edk2SymbolType.infDefine: - return new EdkSymbolInfDefine(textLine, location, true, true, parser); - case Edk2SymbolType.infSource: - return new EdkSymbolInfSource(textLine, location, true, true, parser); - case Edk2SymbolType.infLibrary: - return new EdkSymbolInfLibrary(textLine, location, true, true, parser); - case Edk2SymbolType.infPackage: - return new EdkSymbolInfPackage(textLine, location, true, true, parser); - case Edk2SymbolType.infPpi: - return new EdkSymbolInfPpi(textLine, location, true, true, parser); - case Edk2SymbolType.infProtocol: - return new EdkSymbolInfProtocol(textLine, location, true, true, parser); - case Edk2SymbolType.infPcd: - return new EdkSymbolInfPcd(textLine, location, true, true, parser); - case Edk2SymbolType.infGuid: - return new EdkSymbolInfGuid(textLine, location, true, true, parser); - case Edk2SymbolType.infDepex: - return new EdkSymbolInfDepex(textLine, location, true, true, parser); - case Edk2SymbolType.infBinary: - return new EdkSymbolInfBinary(textLine, location, true, true, parser); - case Edk2SymbolType.infFunction: - return new EdkSymbolInfFunction(textLine, location, true, true, parser); - - - - case Edk2SymbolType.decSection: - return new EdkSymbolDecSection(textLine, location, true, true, parser); - - case Edk2SymbolType.decDefine: - return new EdkSymbolDecDefine(textLine, location, true, true, parser); - - case Edk2SymbolType.decLibrary: - return new EdkSymbolDecLibrary(textLine, location, true, true, parser); - - case Edk2SymbolType.decPackage: - return new EdkSymbolDecPackage(textLine, location, true, true, parser); - - case Edk2SymbolType.decPpi: - return new EdkSymbolDecPpi(textLine, location, true, true, parser); - - case Edk2SymbolType.decProtocol: - return new EdkSymbolDecProtocol(textLine, location, true, true, parser); - - case Edk2SymbolType.decPcd: - return new EdkSymbolDecPcd(textLine, location, true, true, parser); - - case Edk2SymbolType.decGuid: - return new EdkSymbolDecGuid(textLine, location, true, true, parser); - - case Edk2SymbolType.decInclude: - return new EdkSymbolDecIncludes(textLine, location, true, true, parser); - - case Edk2SymbolType.aslDefinitionBlock: - return new EdkSymbolAslDefinitionBlock(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslExternal: - return new EdkSymbolAslExternal(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslScope: - return new EdkSymbolAslScope(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslDevice: - return new EdkSymbolAslDevice(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslName: - return new EdkSymbolAslName(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslMethod: - return new EdkSymbolAslMethod(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslField: - return new EdkSymbolAslField(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslOpRegion: - return new EdkSymbolAslOperationRegion(textLine, location, true, true, parser); - break; - case Edk2SymbolType.aslDefault: - break; - case Edk2SymbolType.vfrDefault: - return new EdkSymbolVfrDefault(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrFormset: - return new EdkSymbolVfrFormset(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrForm: - return new EdkSymbolVfrForm(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrOneof: - return new EdkSymbolVfrOneof(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrCheckbox: - return new EdkSymbolVfrCheckbox(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrString: - return new EdkSymbolVfrString(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrPassword: - return new EdkSymbolVfrPassword(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrNumeric: - return new EdkSymbolVfrNumeric(textLine, location, true, true, parser); - break; - case Edk2SymbolType.vfrGoto: - return new EdkSymbolVfrGoto(textLine, location, true, true, parser); - break; - - case Edk2SymbolType.fdfSection: - return new EdkSymbolFdfSection(textLine, location, true, true, parser); - - case Edk2SymbolType.fdfInf: - return new EdkSymbolFdfInf(textLine, location, true, true, parser); - - case Edk2SymbolType.fdfDefinition: - return new EdkSymbolFdfDefinition(textLine, location, true, true, parser); - - case Edk2SymbolType.fdfFile: - return new EdkSymbolFdfFile(textLine, location, true, true, parser); - - case Edk2SymbolType.fdfInclude: - return new EdkSymbolFdfInclude(textLine, location, true, true, parser); - - - - case Edk2SymbolType.condition: - return new EdkSymbolCondition(textLine, location, true, true, parser); - - case Edk2SymbolType.unknown: - return new EdkSymbolUnknown(textLine, location, true, true, parser); - - default: - gDebugLog.error(`Symbol factory doesnt support: ${type}`); - return undefined; - } - } -} \ No newline at end of file diff --git a/src/symbols/symbolsType.ts b/src/symbols/symbolsType.ts deleted file mode 100644 index c2f179e..0000000 --- a/src/symbols/symbolsType.ts +++ /dev/null @@ -1,136 +0,0 @@ - -export enum Edk2SymbolType { - dscDefine, - dscLibraryDefinition, - dscModuleDefinition, - dscSection, - dscBuildOptionsSection, - dscComponentSubSection, - dscPcdDefinition, - dscBuildOption, - dscInclude, - dscLine, - infDefine, - infSource, - infPackage, - infPpi, - infProtocol, - infPcd, - infGuid, - infDepex, - infLibrary, - infBinary, - infSectionPackages, - infSectionLibraries, - infSectionProtocols, - infSectionPpis, - infSectionGuids, - infSectionDepex, - infSectionPcds, - infSectionSource, - infSection, - infFunction, - decSection, - decDefine, - decPackage, - decPpi, - decProtocol, - decPcd, - decInclude, - decLibrary, - decGuid, - aslDefinitionBlock, - aslExternal, - aslScope, - aslDevice, - aslName, - aslMethod, - aslField, - aslOpRegion, - aslDefault, - vfrDefault, - vfrFormset, - vfrForm, - vfrOneof, - vfrCheckbox, - vfrString, - vfrPassword, - vfrNumeric, - vfrGoto, - fdfSection, - fdfInf, - fdfDefinition, - fdfFile, - fdfInclude, - condition, - unknown, - /** Sentinel used by the workspace tree filter to toggle visibility of inactive nodes. */ - showInactiveNodes, -} - -export var typeToStr: Map = new Map( - [ - [Edk2SymbolType.dscDefine, "dscDefine"], - [Edk2SymbolType.dscLibraryDefinition, "dscLibraryDefinition"], - [Edk2SymbolType.dscModuleDefinition, "dscModuleDefinition"], - [Edk2SymbolType.dscSection, "dscSection"], - [Edk2SymbolType.dscBuildOptionsSection, "dscBuildOptionsSection"], - [Edk2SymbolType.dscComponentSubSection, "dscComponentSubSection"], - [Edk2SymbolType.dscPcdDefinition, "dscPcdDefinition"], - [Edk2SymbolType.dscBuildOption, "dscBuildOption"], - [Edk2SymbolType.dscInclude, "dscInclude"], - [Edk2SymbolType.dscLine, "dscLine"], - [Edk2SymbolType.infDefine, "infDefine"], - [Edk2SymbolType.infSource, "infSource"], - [Edk2SymbolType.infPackage, "infPackage"], - [Edk2SymbolType.infPpi, "infPpi"], - [Edk2SymbolType.infProtocol, "infProtocol"], - [Edk2SymbolType.infPcd, "infPcd"], - [Edk2SymbolType.infGuid, "infGuid"], - [Edk2SymbolType.infDepex, "infDepex"], - [Edk2SymbolType.infLibrary, "infLibrary"], - [Edk2SymbolType.infBinary, "infBinary"], - [Edk2SymbolType.infSectionLibraries, "infSectionLibraries"], - [Edk2SymbolType.infSectionProtocols, "infSectionProtocols"], - [Edk2SymbolType.infSectionPpis, "infSectionPpis"], - [Edk2SymbolType.infSectionGuids, "infSectionGuids"], - [Edk2SymbolType.infSectionDepex, "infSectionDepex"], - [Edk2SymbolType.infSectionPcds, "infSectionPcds"], - [Edk2SymbolType.infSection, "infSection"], - [Edk2SymbolType.infFunction, "infFunction"], - [Edk2SymbolType.decSection, "decSection"], - [Edk2SymbolType.decDefine, "decDefine"], - [Edk2SymbolType.decPackage, "decPackage"], - [Edk2SymbolType.decPpi, "decPpi"], - [Edk2SymbolType.decProtocol, "decProtocol"], - [Edk2SymbolType.decPcd, "decPcd"], - [Edk2SymbolType.decInclude, "decIncludes"], - [Edk2SymbolType.decLibrary, "decLibrary"], - [Edk2SymbolType.decGuid, "decGuid"], - [Edk2SymbolType.aslDefinitionBlock, "aslDefinitionBlock"], - [Edk2SymbolType.aslExternal, "aslExternal"], - [Edk2SymbolType.aslScope, "aslScope"], - [Edk2SymbolType.aslDevice, "aslDevice"], - [Edk2SymbolType.aslName, "aslName"], - [Edk2SymbolType.aslMethod, "aslMethod"], - [Edk2SymbolType.aslField, "aslField"], - [Edk2SymbolType.aslOpRegion, "aslOpRegion"], - [Edk2SymbolType.aslDefault, "aslDefault"], - [Edk2SymbolType.vfrDefault, "vfrDefault"], - [Edk2SymbolType.vfrFormset, "vfrFormset"], - [Edk2SymbolType.vfrForm, "vfrForm"], - [Edk2SymbolType.vfrOneof, "vfrOneof"], - [Edk2SymbolType.vfrCheckbox, "vfrCheckbox"], - [Edk2SymbolType.vfrString, "vfrString"], - [Edk2SymbolType.vfrPassword, "vfrPassword"], - [Edk2SymbolType.vfrNumeric, "vfrNumeric"], - [Edk2SymbolType.vfrGoto, "vfrGoto"], - [Edk2SymbolType.fdfSection, "fdfSection"], - [Edk2SymbolType.fdfInf, "fdfInf"], - [Edk2SymbolType.fdfDefinition, "fdfDefinition"], - [Edk2SymbolType.fdfFile, "fdfFile"], - [Edk2SymbolType.fdfInclude, "fdfInclude"], - [Edk2SymbolType.condition, "condition"], - [Edk2SymbolType.unknown, "unknown"], - ] -); \ No newline at end of file diff --git a/src/symbols/vfrSymbols.ts b/src/symbols/vfrSymbols.ts deleted file mode 100644 index 87d57b1..0000000 --- a/src/symbols/vfrSymbols.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { SymbolKind, Location, SymbolTag, Range, DocumentSymbol } from "vscode"; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import * as vscode from 'vscode'; -import { gEdkWorkspaces, gPathFind } from "../extension"; -import { split, trimSpaces } from "../utils"; -import { WorkspaceDefinitions } from "../index/definitions"; -import { DocumentParser } from "../edkParser/languageParser"; -import { EdkSymbol } from "./edkSymbols"; - -export class EdkSymbolVfrDefault extends EdkSymbol { - - type = Edk2SymbolType.vfrDefault; - kind = vscode.SymbolKind.Null; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrFormset extends EdkSymbol { - - type = Edk2SymbolType.vfrFormset; - kind = vscode.SymbolKind.Class; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrForm extends EdkSymbol { - - type = Edk2SymbolType.vfrForm; - kind = vscode.SymbolKind.Package; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrOneof extends EdkSymbol { - - type = Edk2SymbolType.vfrOneof; - kind = vscode.SymbolKind.Enum; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrCheckbox extends EdkSymbol { - - type = Edk2SymbolType.vfrCheckbox; - kind = vscode.SymbolKind.Boolean; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrString extends EdkSymbol { - - type = Edk2SymbolType.vfrString; - kind = vscode.SymbolKind.String; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrPassword extends EdkSymbol { - - type = Edk2SymbolType.vfrPassword; - kind = vscode.SymbolKind.String; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrNumeric extends EdkSymbol { - - type = Edk2SymbolType.vfrNumeric; - kind = vscode.SymbolKind.Number; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} - -export class EdkSymbolVfrGoto extends EdkSymbol { - - type = Edk2SymbolType.vfrGoto; - kind = vscode.SymbolKind.Event; - - onCompletion: undefined; - onDefinition: undefined; - onHover: undefined; - onDeclaration: undefined; -} \ No newline at end of file diff --git a/src/ternarySearchTree.ts b/src/ternarySearchTree.ts deleted file mode 100644 index def3846..0000000 --- a/src/ternarySearchTree.ts +++ /dev/null @@ -1,155 +0,0 @@ -import * as vscode from 'vscode'; -import { gDebugLog, gWorkspacePath } from './extension'; - -/** - * A node in the Ternary Search Tree. - * Each node stores a single character and branches into three children: - * left – characters less than this node's character - * mid – next character in the same key - * right – characters greater than this node's character - * - * When `isEnd` is true the path from the root through mid-pointers - * spells out a complete key, and `values` holds the associated URIs. - */ -interface TSTNode { - char: string; - left: TSTNode | null; - mid: TSTNode | null; - right: TSTNode | null; - isEnd: boolean; - values: vscode.Uri[]; -} - -/** - * Ternary Search Tree used as a temporary in-memory file index. - * - * Built when the workspace is cleared and being rebuilt so that - * `PathFind.findPath` can resolve file names without waiting for - * `vscode.workspace.findFiles` (which may be slow / stale during - * a rebuild). - * - * Keys are **lower-cased file basenames** so look-ups are - * case-insensitive. Each key maps to one or more `vscode.Uri`s. - */ -export class TernarySearchTree { - private root: TSTNode | null = null; - private _size: number = 0; - - /** Number of unique keys stored in the tree. */ - get size(): number { - return this._size; - } - - // ── Insertion ──────────────────────────────────────────────── - - /** - * Insert a key → value pair into the tree. - * If the key already exists the value is appended to its list. - */ - insert(key: string, value: vscode.Uri): void { - if (key.length === 0) { return; } - this.root = this._insert(this.root, key, value, 0); - } - - private _insert(node: TSTNode | null, key: string, value: vscode.Uri, idx: number): TSTNode { - const ch = key[idx]; - - if (node === null) { - node = { char: ch, left: null, mid: null, right: null, isEnd: false, values: [] }; - } - - if (ch < node.char) { - node.left = this._insert(node.left, key, value, idx); - } else if (ch > node.char) { - node.right = this._insert(node.right, key, value, idx); - } else if (idx < key.length - 1) { - node.mid = this._insert(node.mid, key, value, idx + 1); - } else { - if (!node.isEnd) { - node.isEnd = true; - this._size++; - } - node.values.push(value); - } - - return node; - } - - // ── Exact-match search ─────────────────────────────────────── - - /** - * Return all URIs associated with `key`, or an empty array if not found. - */ - search(key: string): vscode.Uri[] { - if (key.length === 0) { return []; } - const node = this._search(this.root, key, 0); - if (node && node.isEnd) { - return node.values; - } - return []; - } - - private _search(node: TSTNode | null, key: string, idx: number): TSTNode | null { - if (node === null) { return null; } - - const ch = key[idx]; - - if (ch < node.char) { - return this._search(node.left, key, idx); - } else if (ch > node.char) { - return this._search(node.right, key, idx); - } else if (idx < key.length - 1) { - return this._search(node.mid, key, idx + 1); - } else { - return node; - } - } - - // ── Bulk build ─────────────────────────────────────────────── - - /** - * Scan *all* files in the workspace and index them by their - * lower-cased basename. Returns the number of files indexed. - */ - async buildFromWorkspace(): Promise { - const startTime = Date.now(); - gDebugLog.info('TernarySearchTree: building file index from workspace…'); - - // findFiles with ** grabs every file in the workspace - const allFiles = await vscode.workspace.findFiles('**/*', null); - - for (const uri of allFiles) { - const baseName = this.baseName(uri); - this.insert(baseName, uri); - } - - const elapsed = Date.now() - startTime; - gDebugLog.info(`TernarySearchTree: indexed ${allFiles.length} files (${this._size} unique names) in ${elapsed} ms`); - return allFiles.length; - } - - // ── Helpers ────────────────────────────────────────────────── - - /** - * Return the lower-cased basename of a URI (case-insensitive keys). - */ - private baseName(uri: vscode.Uri): string { - const segments = uri.fsPath.split(/[\\/]/); - return (segments[segments.length - 1] || '').toLowerCase(); - } - - /** - * Look up a file by its basename string (case-insensitive). - */ - findFilesByName(fileName: string): vscode.Uri[] { - return this.search(fileName.toLowerCase()); - } - - /** - * Clear the tree and release memory. - */ - dispose(): void { - this.root = null; - this._size = 0; - } -} diff --git a/src/test/runTest.ts b/src/test/runTest.ts deleted file mode 100644 index 27b3ceb..0000000 --- a/src/test/runTest.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as path from 'path'; - -import { runTests } from '@vscode/test-electron'; - -async function main() { - try { - // The folder containing the Extension Manifest package.json - // Passed to `--extensionDevelopmentPath` - const extensionDevelopmentPath = path.resolve(__dirname, '../../'); - - // The path to test runner - // Passed to --extensionTestsPath - const extensionTestsPath = path.resolve(__dirname, './suite/index'); - - // Download VS Code, unzip it and run the integration test - await runTests({ extensionDevelopmentPath, extensionTestsPath }); - } catch (err) { - console.error('Failed to run tests'); - process.exit(1); - } -} - -main(); diff --git a/src/test/suite/README.md b/src/test/suite/README.md deleted file mode 100644 index b9876d6..0000000 --- a/src/test/suite/README.md +++ /dev/null @@ -1,461 +0,0 @@ -# Test Suite - -Integration tests for the Edk2Code VS Code extension. -Tests run under Mocha (TDD UI) via `@vscode/test-electron`. - -## Running Tests - -- **VS Code**: Use the **Extension Tests** launch configuration (F5). -- **CLI**: `node ./out/test/runTest.js` (bypasses lint). - -## Fixture Files - -Test fixtures live in the `test/` folder at the repository root: - -| Fixture | Used By | -|---------|---------| -| `testDscParsing.dsc` | `dscParser.test.ts`, `edkWorkspace.test.ts` | -| `testDecParsing.dec` | `decParser.test.ts` | -| `testFdfParsing.fdf` | `fdfParser.test.ts`, `edkWorkspace.test.ts` | -| `testInfParsing.inf` | `infParser.test.ts` | -| `testAslParsing.asl` | `aslParser.test.ts` | -| `testVfrParsing.vfr` | `vfrParser.test.ts` | -| `testDscProcess.dsc` | `edkWorkspaceProcess.test.ts` | - ---- - -## Test Files — Detailed Breakdown - -### `extension.test.ts` - -**Suite: Extension Test Suite** — Smoke test that validates the test harness is working. - -| # | Test | Description | -|---|------|-------------| -| 1 | Sample test | Asserts `Array.indexOf` returns `-1` for missing elements. Proves the Mocha runner and VS Code test host are functional. | - ---- - -### `dscParser.test.ts` - -**Suite: DSC Parser – Symbol Extraction** — Parses `test/testDscParsing.dsc` with `DscParser` and validates that all DSC symbol types are correctly extracted. The fixture includes `[Defines]`, `[SkuIds]`, `[LibraryClasses]` (common + `.X64`), `[Components]` (common + `.X64` with sub-sections), PCD sections, `[BuildOptions]`, root-level `DEFINE`, `!include`, and block comments. - -| # | Test | Description | -|---|------|-------------| -| 1 | Parses [Defines] section | At least one `dscSection` symbol with name matching "defines". | -| 2 | Parses [LibraryClasses] sections (common + arch-specific) | At least 2 `dscSection` symbols for `LibraryClasses` (common and `.X64`). | -| 3 | Parses [Components] and [Components.X64] sections | At least 2 `dscSection` symbols for `Components`. | -| 4 | Parses [SkuIds] section | Exactly 1 `dscSection` symbol for `SkuIds`. | -| 5 | Parses [BuildOptions] section | At least 1 `dscBuildOptionsSection` symbol. | -| 6 | Parses PCD sections (FixedAtBuild + DynamicDefault) | At least 2 `dscSection` symbols with names matching "pcd". | -| 7 | Parses DEFINE statements inside [Defines] | At least 3 `dscDefine` symbols (`DEFINE MY_VAR`, `DEFINE EMPTY_VAR`, `ROOT_DEFINE`). | -| 8 | DEFINE with empty value is still parsed | Finds `EMPTY_VAR` in the define list (covers `DEFINE EMPTY_VAR=`). | -| 9 | Root-level DEFINE (outside section) is parsed | Finds `ROOT_DEFINE` as a `dscDefine` (defined outside any section header). | -| 10 | Parses library class definitions | At least 4 `dscLibraryDefinition` symbols (BaseLib, DebugLib, PrintLib, TimerLib, plus overrides). | -| 11 | Library definition with extra whitespace around pipe is parsed | Finds `PrintLib` even when the line has extra spaces around `\|`. | -| 12 | Parses simple .inf module references | At least 3 `dscModuleDefinition` symbols. | -| 13 | Module with sub-sections (curly braces) is parsed | Finds `ComplexModule.inf` and asserts it has `children.length > 0`. | -| 14 | Component sub-sections are parsed | At least 2 `dscComponentSubSection` symbols (``, ``, ``). | -| 15 | Parses PCD definitions | At least 3 `dscPcdDefinition` symbols across FixedAtBuild, DynamicDefault, and component-scoped PCDs. | -| 16 | Parses build option entries | At least 2 `dscBuildOption` symbols (GCC and MSFT lines). | -| 17 | Parses !include directive | At least 1 `dscInclude` symbol; specifically finds `TestInclude.dsc.inc`. | -| 18 | symbolsTree contains top-level section nodes | `symbolsTree` is non-empty and every root node has an expected DSC symbol type. | -| 19 | Library definitions are children of their parent section | The `[LibraryClasses]` section node contains at least 3 child `dscLibraryDefinition` symbols. | -| 20 | symbolsList length equals total nodes across the tree | Flat `symbolsList.length` equals recursive count of all nodes in `symbolsTree`. | -| 21 | Comments are not parsed as symbols | No symbol name starts with `#`. | - ---- - -### `decParser.test.ts` - -**Suite: DEC Parser – Symbol Extraction** — Parses `test/testDecParsing.dec` with `DecParser`. The fixture includes `[Defines]`, `[Includes]` (common + `.X64`), `[LibraryClasses]`, `[Guids]` with GUID-format values, `[Protocols]`, `[Ppis]`, `[PcdsFixedAtBuild]`, and `[PcdsPatchableInModule]`. - -| # | Test | Description | -|---|------|-------------| -| 1 | Parses [Defines] section | At least 1 `decSection` matching "defines". | -| 2 | Parses [Includes] sections (common + arch-specific) | At least 2 `decSection` symbols for `Includes` (common and `.X64`). | -| 3 | Parses [LibraryClasses] section | At least 1 `decSection` matching "libraryclasses". | -| 4 | Parses [Guids] section | At least 1 `decSection` matching "guids". | -| 5 | Parses [Protocols] section | At least 1 `decSection` matching "protocols". | -| 6 | Parses [Ppis] section | At least 1 `decSection` matching "ppis". | -| 7 | Parses PCD sections | At least 2 `decSection` symbols with names matching "pcds" (FixedAtBuild + PatchableInModule). | -| 8 | Parses include directory entries | At least 2 `decInclude` symbols (e.g. `Include`, `Include/Library`). | -| 9 | Parses library class entries | At least 2 `decLibrary` symbols. | -| 10 | Parses GUID entries | At least 1 `decGuid` symbol with GUID-format value. | -| 11 | Parses protocol entries | At least 2 `decProtocol` symbols. | -| 12 | Parses PPI entries | At least 1 `decPpi` symbol. | -| 13 | Parses PCD entries | At least 2 `decPcd` symbols across different PCD sections. | -| 14 | symbolsTree is not empty | `symbolsTree.length > 0`. | -| 15 | symbolsList equals recursive tree count | Flat list count matches recursive tree traversal count. | -| 16 | Comments are not parsed as symbols | No symbol name starts with `#`. | - ---- - -### `fdfParser.test.ts` - -**Suite: FDF Parser – Symbol Extraction** — Parses `test/testFdfParsing.fdf` with `FdfParser`. The fixture includes `[FD.TestFd]`, `[FV.FVMAIN]` with INF entries and a `DEFINE`, `[FV.FVRECOVERY]` with an `APRIORI` block, `[Rule.Common.SEC]`, and `!include`. - -| # | Test | Description | -|---|------|-------------| -| 1 | Parses [FD.*] section | At least 1 `fdfSection` matching "FD.". | -| 2 | Parses [FV.*] sections | At least 2 `fdfSection` symbols matching "FV." (FVMAIN and FVRECOVERY). | -| 3 | Parses [Rule.*] section | At least 1 `fdfSection` matching "Rule.". | -| 4 | Parses INF module references | At least 3 `fdfInf` symbols (SimpleModule, AnotherModule, AprioriModule, RecoveryModule). | -| 5 | Parses DEFINE statements | At least 2 `fdfDefinition` symbols. | -| 6 | Parses !include directive | At least 1 `fdfInclude` symbol; specifically finds `TestFdfInclude.fdf.inc`. | -| 7 | symbolsTree is not empty | `symbolsTree.length > 0`. | -| 8 | symbolsList equals recursive tree count | Flat list count matches recursive tree traversal count. | -| 9 | Comments are not parsed as symbols | No symbol name starts with `#`. | - ---- - -### `infParser.test.ts` - -**Suite: INF Parser – Symbol Extraction** — Parses `test/testInfParsing.inf` with `InfParser`. The fixture includes `[Defines]` (INF_VERSION, BASE_NAME, MODULE_TYPE, ENTRY_POINT, LIBRARY_CLASS, CONSTRUCTOR, DESTRUCTOR, DEFINE), `[Sources]` + `[Sources.X64]`, `[Packages]`, `[LibraryClasses]`, `[Protocols]`, `[Ppis]`, `[Guids]`, `[FixedPcd]`, and `[Depex]`. - -| # | Test | Description | -|---|------|-------------| -| 1 | Parses [Defines] section | At least 1 `infSection` matching "defines". | -| 2 | Parses [Sources] section(s) | At least 1 `infSectionSource` symbol. | -| 3 | Parses [Packages] section | At least 1 `infSectionPackages` symbol. | -| 4 | Parses [LibraryClasses] section | At least 1 `infSectionLibraries` symbol. | -| 5 | Parses [Protocols] section | At least 1 `infSectionProtocols` symbol. | -| 6 | Parses [Ppis] section | At least 1 `infSectionPpis` symbol. | -| 7 | Parses [Guids] section | At least 1 `infSectionGuids` symbol. | -| 8 | Parses [Pcd] / [FixedPcd] section | At least 1 `infSectionPcds` symbol. | -| 9 | Parses [Depex] section | At least 1 `infSectionDepex` symbol. | -| 10 | Parses INF defines (MODULE_TYPE, BASE_NAME, etc.) | At least 7 `infDefine` symbols covering all key-value pairs in `[Defines]`. | -| 11 | Parses ENTRY_POINT define | Finds a define with name matching `ENTRY_POINT`. | -| 12 | Parses CONSTRUCTOR define | Finds a define with name matching `CONSTRUCTOR`. | -| 13 | Parses DESTRUCTOR define | Finds a define with name matching `DESTRUCTOR`. | -| 14 | Parses source file entries | At least 3 `infSource` symbols (`.c`, `.h`, arch-specific). | -| 15 | Parses package references | At least 2 `infPackage` symbols (e.g. `MdePkg/MdePkg.dec`). | -| 16 | Parses library class references | At least 3 `infLibrary` symbols. | -| 17 | Parses protocol entries | At least 2 `infProtocol` symbols. | -| 18 | Parses PPI entries | At least 1 `infPpi` symbol. | -| 19 | Parses GUID entries | At least 2 `infGuid` symbols. | -| 20 | Parses PCD entries | At least 1 `infPcd` symbol. | -| 21 | Parses dependency expression entries | At least 1 `infDepex` symbol. | -| 22 | symbolsTree is not empty | `symbolsTree.length > 0`. | -| 23 | symbolsList equals recursive tree count | Flat list count matches recursive tree traversal count. | -| 24 | Comments are not parsed as symbols | No symbol name starts with `#`. | - ---- - -### `aslParser.test.ts` - -**Suite: ASL Parser – Symbol Extraction** — Parses `test/testAslParsing.asl` with `AslParser`. The fixture includes a `DefinitionBlock`, 2 `External` declarations, 2 `Scope` blocks, 2 `Device` blocks (TPM0 with Name/Method/OperationRegion/Field, EC0 with Name/Method/OperationRegion/Field). - -| # | Test | Description | -|---|------|-------------| -| 1 | Parses DefinitionBlock | At least 1 `aslDefinitionBlock` symbol. | -| 2 | Parses External declarations | At least 2 `aslExternal` symbols (`\_SB.PCI0`, `\_SB.PCI0.LPCB`). | -| 3 | Parses Scope blocks | At least 2 `aslScope` symbols (`\_SB`, `\_SB.PCI0`). | -| 4 | Parses Device blocks | At least 2 `aslDevice` symbols (`TPM0`, `EC0`). | -| 5 | Parses Name declarations | At least 4 `aslName` symbols (TVAR, _HID, _STR, PVAR, RBUF, etc.). | -| 6 | Parses Method blocks | At least 2 `aslMethod` symbols (_STA, _CRS, RFAN). | -| 7 | Parses OperationRegion declarations | At least 2 `aslOpRegion` symbols (TPMR, ECOR). | -| 8 | Parses Field declarations | At least 2 `aslField` symbols (Field on TPMR, Field on ECOR). | -| 9 | DefinitionBlock has children | The first `aslDefinitionBlock` has `children.length > 0`. | -| 10 | Device contains Names as children | `TPM0` device's children include at least one `aslName`. | -| 11 | symbolsTree is not empty | `symbolsTree.length > 0`. | -| 12 | symbolsList equals recursive tree count | Flat list count matches recursive tree traversal count. | -| 13 | Comments are not parsed as symbols | No symbol name starts with `//`. | - ---- - -### `vfrParser.test.ts` - -**Suite: VFR Parser – Symbol Extraction** — Parses `test/testVfrParsing.vfr` with `VfrParser`. The fixture includes a `formset` containing 2 `form` blocks, `oneof`, `checkbox`, `numeric`, `string`, `password`, and `goto` controls. - -| # | Test | Description | -|---|------|-------------| -| 1 | Parses formset | At least 1 `vfrFormset` symbol. | -| 2 | Parses form blocks | Checks for `vfrForm` symbols. Note: the VFR parser does not nest `BlockFormSection` inside `BlockFormsetSection.context`, so `form` blocks inside `formset` may not be parsed. The test validates the parser does not crash. | -| 3 | Parses oneof controls | At least 2 `vfrOneof` symbols (Option1, Option2). | -| 4 | Parses checkbox controls | At least 1 `vfrCheckbox` symbol. | -| 5 | Parses numeric controls | At least 1 `vfrNumeric` symbol. | -| 6 | Parses string controls | At least 1 `vfrString` symbol. | -| 7 | Parses password controls | At least 1 `vfrPassword` symbol. | -| 8 | Parses goto references | At least 2 `vfrGoto` symbols (goto to form IDs). | -| 9 | Parses prompt entries inside controls | At least 2 `vfrString` symbols from `prompt` lines inside controls and the standalone string control. | -| 10 | symbolsTree is not empty | `symbolsTree.length > 0`. | -| 11 | Formset or form has children | At least one `vfrFormset` or `vfrForm` symbol has `children.length > 0`. | -| 12 | symbolsList equals recursive tree count | Flat list count matches recursive tree traversal count. | -| 13 | Comments are not parsed as symbols | No symbol name starts with `//`. | - ---- - -### `edkWorkspace.test.ts` - -Tests the workspace index classes from `src/index/edkWorkspace.ts`. These are unit-style tests that construct objects directly without running the full workspace processing pipeline. - -#### Suite: SectionProperty - -| # | Test | Description | -|---|------|-------------| -| 1 | constructor lowercases all fields | `SectionProperty('LibraryClasses', 'X64', 'DXE_DRIVER')` stores all values in lowercase. | -| 2 | constructor with already lowercase values | Passing already-lowercase strings preserves them unchanged. | - -#### Suite: SectionProperties - -| # | Test | Description | -|---|------|-------------| -| 1 | starts with empty properties | A new `SectionProperties()` has `properties.length === 0`. | -| 2 | addProperty adds correctly | After `addProperty('LibraryClasses', 'X64', 'DXE_DRIVER')`, length is 1 and sectionType is lowercased. | -| 3 | addProperty multiple | Adding 2 properties results in `properties.length === 2`. | -| 4 | compareArch returns true for matching arch | Two `SectionProperties` sharing `X64` arch return `true`. | -| 5 | compareArch returns false for different archs | `X64` vs `IA32` returns `false`. | -| 6 | compareArchStr returns true for matching arch string | Matches case-insensitively (both `'X64'` and `'x64'` match). | -| 7 | compareArchStr returns false for non-matching arch | `'IA32'` does not match an `X64`-only property set. | -| 8 | compareLibSectionType returns true for matching section type | Two `SectionProperties` both with `LibraryClasses` section type return `true`. | -| 9 | compareLibSectionType returns false for different section types | `LibraryClasses` vs `Components` returns `false`. | -| 10 | compareLibSectionTypeStr case-insensitive match | `'LibraryClasses'`, `'libraryclasses'`, and `'LIBRARYCLASSES'` all match. | -| 11 | compareLibSectionTypeStr returns false for non-matching | `'LibraryClasses'` does not match a `Components`-only property set. | -| 12 | compareModuleType returns true for matching module type | Two properties sharing `DXE_DRIVER` return `true`. | -| 13 | compareModuleType returns false for different module types | `DXE_DRIVER` vs `PEIM` returns `false`. | -| 14 | compareModuleTypeStr case-insensitive | Both `'DXE_DRIVER'` and `'dxe_driver'` match. | -| 15 | compareModuleTypeStr returns false for non-matching | `'PEIM'` does not match a `DXE_DRIVER`-only property set. | -| 16 | toString returns comma-separated properties | With 2 properties added, `toString()` output contains a comma. | -| 17 | compareArch matches any combination | A property set with both `X64` and `IA32` entries matches another set with only `IA32`. | - -#### Suite: InfDsc - -| # | Test | Description | -|---|------|-------------| -| 1 | constructor with section parent sets sectionProperties | Parent `'Components.X64'` sets `parent = undefined` and populates `sectionProperties` with `components/x64/common`. | -| 2 | constructor with INF parent sets parent path | Parent `'SomeModule/Module.inf'` (ending in `.inf`) sets `parent` to the normalized path and leaves `sectionProperties` empty. | -| 3 | constructor normalizes path separators | Forward slashes in the file path are replaced with `path.sep`. | -| 4 | constructor with multi-section parent | Parent `'LibraryClasses.X64.DXE_DRIVER,LibraryClasses.IA32.PEIM'` creates 2 section properties with correct arch and moduleType. | -| 5 | constructor with section missing arch defaults to common | Parent `'libraryclasses'` defaults both arch and moduleType to `'common'`. | -| 6 | getModuleTypeStr returns comma-separated module types | Multi-property InfDsc returns `'dxe_driver,peim'`. | -| 7 | getModuleTypeStr single property | Single `'Components.X64'` property returns `'common'` (moduleType defaults). | -| 8 | toString includes path and line number | `toString()` of an InfDsc at line 42 contains `'42'`. | -| 9 | text property stores original line | The `text` field preserves the raw DSC line text passed to the constructor. | -| 10 | location is preserved | The `vscode.Location` passed to the constructor is stored as-is (line 99). | - -#### Suite: EdkWorkspaces - -| # | Test | Description | -|---|------|-------------| -| 1 | isConfigured returns false when no workspaces | A fresh `EdkWorkspaces()` with no workspaces added returns `false`. | -| 2 | isConfigured returns true after adding a workspace | After pushing an `EdkWorkspace` into `workspaces`, returns `true`. | -| 3 | getInstance returns singleton | Two calls to `EdkWorkspaces.getInstance()` return the same reference. | -| 4 | isFileInUse returns undefined when no workspaces | With no workspaces, `isFileInUse()` returns `undefined` (indeterminate). | -| 5 | getWorkspace returns empty array when no workspaces | Returns `[]` when no workspaces are configured. | -| 6 | getDefinition returns undefined when no workspaces | Returns `undefined` for any variable lookup with no workspaces. | -| 7 | replaceDefines returns original text when no workspaces | `'$(MY_VAR)/path'` is returned unchanged when no workspace can resolve it. | -| 8 | getLib returns empty array when no workspaces | Returns `[]` for any location lookup with no workspaces. | - -#### Suite: EdkWorkspace - -| # | Test | Description | -|---|------|-------------| -| 1 | constructor sets mainDsc from document | `mainDsc.fsPath` ends with `testDscParsing.dsc`. | -| 2 | constructor generates a numeric id | `id` is a `number` and `> 0`. | -| 3 | platformName starts as undefined | Before `proccessWorkspace()`, `platformName` is `undefined`. | -| 4 | flashDefinitionDocument starts as undefined | Before processing, `flashDefinitionDocument` is `undefined`. | -| 5 | filesLibraries starts empty | `filesLibraries.length === 0`. | -| 6 | filesModules starts empty | `filesModules.length === 0`. | -| 7 | dscList is initially empty | `dscList()` returns `[]` before any processing. | -| 8 | fdfList is initially empty | `fdfList()` returns `[]` before any processing. | -| 9 | getFilesList aggregates all file lists | Returns an array combining DSC, FDF, module, and library paths. | -| 10 | includeTree starts empty | `includeTree.length === 0`. | -| 11 | getDefinitions returns a Map | The defines map is a `Map` instance even before processing. | -| 12 | getDefinition returns undefined for unknown key | `getDefinition('NON_EXISTENT')` returns `undefined`. | -| 13 | getDefinitionLocation returns undefined for unknown key | `getDefinitionLocation('NON_EXISTENT')` returns `undefined`. | -| 14 | replaceDefine passes through text with no defines | `'$(UNKNOWN_VAR)/path'` is unchanged when no defines are set. | -| 15 | getPcds returns undefined for unknown namespace | `getPcds('gUnknownPkg')` returns `undefined`. | -| 16 | getAllPcds returns a Map | PCD definitions map is a `Map` instance. | -| 17 | filesLibraries can be set | Setting via the property setter and reading back works correctly. | -| 18 | filesModules can be set | Setting via the property setter and reading back works correctly. | -| 19 | getFilesList includes libraries and modules | After setting both, `getFilesList()` returns at least 2 paths. | -| 20 | filesDsc can be set and read | Setting the `Set` and reading `dscList()` returns 1 entry. | -| 21 | filesFdf can be set and read | Setting the `Set` and reading `fdfList()` returns 1 entry. | -| 22 | getLib returns undefined when no matching library | A non-matching location returns `undefined`. | -| 23 | getLib finds matching library by location | An InfDsc with the exact same URI and line is found by `getLib()`. | - -#### Suite: EdkWorkspace.evaluateExpression - -Tests the Shunting-Yard expression evaluator used for `!if` / `!ifdef` / `!ifndef` conditional processing. - -| # | Test | Description | -|---|------|-------------| -| 1 | TRUE evaluates to true | Literal `TRUE` → `true`. | -| 2 | FALSE evaluates to false | Literal `FALSE` → `false`. | -| 3 | true/false case-insensitive | `'true'`, `'True'`, `'false'` all parse correctly. | -| 4 | numeric 1 is truthy | `'1'` → `1`. | -| 5 | numeric 0 is falsy | `'0'` → `0`. | -| 6 | == with matching strings | `'"hello" == "hello"'` → `true`. | -| 7 | == with non-matching strings | `'"hello" == "world"'` → `false`. | -| 8 | != with different strings | `'"hello" != "world"'` → `true`. | -| 9 | != with same strings | `'"hello" != "hello"'` → `false`. | -| 10 | EQ operator | `'"a" EQ "a"'` → `true` (EDK2-style equality). | -| 11 | NE operator | `'"a" NE "b"'` → `true` (EDK2-style inequality). | -| 12 | AND with both true | `'TRUE AND TRUE'` → `true`. | -| 13 | AND with one false | `'TRUE AND FALSE'` → `false`. | -| 14 | OR with one true | `'FALSE OR TRUE'` → `true`. | -| 15 | OR with both false | `'FALSE OR FALSE'` → `false`. | -| 16 | && operator | `'TRUE && TRUE'` → `true` (C-style AND). | -| 17 | \|\| operator | `'FALSE \|\| TRUE'` → `true` (C-style OR). | -| 18 | NOT TRUE evaluates to false | `'NOT TRUE'` → `false` (unary NOT). | -| 19 | NOT FALSE evaluates to true | `'NOT FALSE'` → truthy. | -| 20 | addition | `'3 + 2'` → `5`. | -| 21 | subtraction | `'5 - 2'` → `3`. | -| 22 | multiplication | `'3 * 4'` → `12`. | -| 23 | division | `'10 / 2'` → `5`. | -| 24 | modulus | `'10 % 3'` → `1`. | -| 25 | greater than | `'5 > 3'` → `true`. | -| 26 | less than | `'3 > 5'` → `false`. | -| 27 | greater or equal | `'5 >= 5'` → `true`. | -| 28 | less or equal | `'3 <= 5'` → `true`. | -| 29 | parentheses group expressions | `'(TRUE OR FALSE) AND TRUE'` → `true`. | -| 30 | nested parentheses | `'((1 + 2) * 3)'` → `9`. | -| 31 | unbalanced parentheses throw | `'(TRUE AND FALSE'` throws an error. | -| 32 | IN operator with match | `'"X64" IN "X64 IA32 ARM"'` → `true`. | -| 33 | IN operator without match | `'"AARCH64" IN "X64 IA32 ARM"'` → `false`. | -| 34 | undefined variable evaluates to false | `'"???"'` (the undefined-variable sentinel) → `false`. | -| 35 | bare word is treated as quoted string | `'hello == "hello"'` → `true` (unquoted words auto-quoted). | -| 36 | complex: (1 + 2) > 2 AND TRUE | Mixed arithmetic + comparison + logical → `true`. | -| 37 | complex: FALSE OR (5 == 5) | Logical OR with parenthesised equality → `true`. | - ---- - -### `edkWorkspaceProcess.test.ts` - -Integration tests for the core workspace processing pipeline: `proccessWorkspace()`, `_doProccessWorkspace()`, and `_processDocument()`. Uses the `test/testDscProcess.dsc` fixture which includes `[Defines]`, `[LibraryClasses]`, `[Components]`, PCD sections, `[BuildOptions]`, conditional blocks (`!if`/`!ifdef`/`!ifndef`/`!else`/`!endif`), nested conditionals, and comments. - -A `ensureProcessingGlobals()` helper stubs all required globals: `gDebugLog`, `gWorkspacePath`, `gConfigAgent`, `gPathFind`, `edkWorkspaceTreeProvider`, `DiagnosticManager`, and `edkStatusBar.myStatusBarItem`. - -#### Suite: EdkWorkspace._processDocument - -Processes the DSC fixture via the private `_processDocument(doc, 'DSC')` and validates all extracted data. - -##### Document Registration - -| # | Test | Description | -|---|------|-------------| -| 1 | Adds document to filesDsc | `dscList()` contains at least 1 entry ending with `testDscProcess.dsc`. | -| 2 | isDocumentInIndex returns true after processing | Private `isDocumentInIndex(doc)` returns `true` for the processed document. | -| 3 | Processing same document twice is a no-op | Calling `_processDocument` again does not add a duplicate entry to `dscList()`. | - -##### Defines Extraction - -| # | Test | Description | -|---|------|-------------| -| 4 | Extracts PLATFORM_NAME from [Defines] | `getDefinition('PLATFORM_NAME')` returns `'TestProcess'`. | -| 5 | Extracts PLATFORM_GUID | `getDefinition('PLATFORM_GUID')` returns `'11111111-2222-3333-4444-555555555555'`. | -| 6 | Extracts DEFINE MY_FLAG | `getDefinition('MY_FLAG')` returns `'TRUE'`. | -| 7 | Extracts DEFINE with empty value | `getDefinition('EMPTY_DEF')` is defined but trims to empty string. | -| 8 | Extracts root-level DEFINE | `getDefinition('ROOT_DEF')` returns `'RootValue'` (defined outside any section). | -| 9 | getDefinitionLocation returns a Location for known define | Location URI ends with `testDscProcess.dsc`. | -| 10 | getDefinitions returns all defines as a Map | Map instance with `size >= 5`. | - -##### Define Variable Substitution - -| # | Test | Description | -|---|------|-------------| -| 11 | DERIVED define has $(BASE) resolved | `DEFINE DERIVED = $(BASE)World` resolves to `'HelloWorld'`. | -| 12 | replaceDefine substitutes known variables | `replaceDefine('$(MY_FLAG)')` returns `'TRUE'`. | -| 13 | replaceDefine leaves unknown variables untouched | `'$(TOTALLY_UNKNOWN)'` passes through unchanged. | - -##### PCD Extraction - -| # | Test | Description | -|---|------|-------------| -| 14 | Extracts PCDs in gTestPkg namespace | `getPcds('gTestPkg')` is not `undefined`. | -| 15 | PcdTestMask has correct value | `PcdTestMask.value` is `'0x2F'`. | -| 16 | PcdBootTimeout from DynamicDefault | `PcdBootTimeout.value` is `'5'`. | -| 17 | PCD with L"string" value strips L prefix | `PcdStringVal.value` starts with `'"'` (L prefix removed). | -| 18 | PCD has location information | PCD position URI ends with `testDscProcess.dsc`. | -| 19 | getAllPcds returns all namespaces | Map contains `'gTestPkg'` key. | - -##### Conditional Processing - -| # | Test | Description | -|---|------|-------------| -| 20 | !if TRUE branch: COND_TAKEN is defined | `getDefinition('COND_TAKEN')` returns `'IfTrueValue'`. | -| 21 | !if TRUE branch: else branch not taken | `COND_TAKEN` is not `'IfFalseValue'`. | -| 22 | !if FALSE: else branch taken, COND_ELSE is defined | `getDefinition('COND_ELSE')` returns `'ElseValue'`. | -| 23 | !if FALSE: if branch not taken, COND_FALSE_IF not defined | `getDefinition('COND_FALSE_IF')` returns `undefined`. | -| 24 | Nested conditionals: outer TRUE inner FALSE -> INNER_ELSE defined | Both `OUTER_TRUE` (`'OuterOk'`) and `INNER_ELSE` (`'InnerElseOk'`) are set. | -| 25 | Nested conditionals: INNER_FALSE not defined | `getDefinition('INNER_FALSE')` returns `undefined`. | -| 26 | !ifdef on existing variable takes the branch | `IFDEF_TAKEN` is `'yes'` (variable `EXISTING_VAR` was defined). | -| 27 | !ifndef on undefined variable takes the branch | `IFNDEF_TAKEN` is `'yes'` (`TOTALLY_UNDEFINED_XYZ` not defined). | -| 28 | COND_A before conditional is still defined | `getDefinition('COND_A')` returns `'BeforeIf'`. | - -##### Library and Module References - -| # | Test | Description | -|---|------|-------------| -| 29 | Libraries are collected (even if paths unresolved) | `filesLibraries.length >= 2` (BaseLib, DebugLib, TimerLib). | -| 30 | Modules are collected (even if paths unresolved) | `filesModules.length >= 2` (ModuleA, ModuleB, ModuleC). | -| 31 | Library InfDsc has correct section properties | BaseLib's `sectionProperties.properties.length > 0`. | -| 32 | Module InfDsc preserves location | First module's location URI ends with `testDscProcess.dsc`. | - -##### Grayout Ranges - -| # | Test | Description | -|---|------|-------------| -| 33 | parsedDocuments has entry for processed document | Private `parsedDocuments` map contains an entry for the document's `fsPath`. | -| 34 | Grayout ranges exist for inactive conditional blocks | At least 1 grayout range from `!if FALSE` blocks. | - -##### Comment Stripping - -| # | Test | Description | -|---|------|-------------| -| 35 | stripComment removes line comments | `'DEFINE X = 1 # comment'` → `'DEFINE X = 1'`. | -| 36 | stripComment preserves hash inside quotes | `'DEFINE X = "value#with#hash"'` → unchanged. | -| 37 | stripComment trims whitespace | `' some text '` → `'some text'`. | -| 38 | stripComment returns empty for comment-only line | `'# just a comment'` → `''`. | - -#### Suite: EdkWorkspace._doProccessWorkspace - -Runs the full private `_doProccessWorkspace()` pipeline (reset state → open main DSC → process → populate `platformName` → find FDF). - -##### Workspace Initialization - -| # | Test | Description | -|---|------|-------------| -| 1 | platformName is populated from PLATFORM_NAME define | `platformName` is `'TestProcess'` after processing. | -| 2 | workInProgress is false after completion | Private `workInProgress` is `false`. | -| 3 | processComplete is true after completion | Private `processComplete` is `true`. | - -##### State Reset - -| # | Test | Description | -|---|------|-------------| -| 4 | Running again resets and re-processes | Second call returns `true` and `platformName` is still `'TestProcess'`. | -| 5 | Returns false if already in progress | Setting `workInProgress = true` causes the method to return `false`. | - -##### Defines After Full Processing - -| # | Test | Description | -|---|------|-------------| -| 6 | All defines from [Defines] section are available | Map has `PLATFORM_NAME`, `MY_FLAG`, `MY_PATH`. | -| 7 | Conditional defines are correctly resolved | `COND_TAKEN` is `'IfTrueValue'`, `COND_ELSE` is `'ElseValue'`. | -| 8 | replaceDefine works after processing | `replaceDefine('$(PLATFORM_NAME)')` returns `'TestProcess'`. | - -##### PCDs After Full Processing - -| # | Test | Description | -|---|------|-------------| -| 9 | PCDs are available after processing | `getPcds('gTestPkg')` has `size >= 3`. | - -##### File Lists After Full Processing - -| # | Test | Description | -|---|------|-------------| -| 10 | dscList contains the main document | At least 1 entry ending with `testDscProcess.dsc`. | -| 11 | Libraries are populated | `filesLibraries.length >= 2`. | -| 12 | Modules are populated | `filesModules.length >= 2`. | -| 13 | getFilesList aggregates all lists | Total `length >= 4` (DSC + libraries + modules). | - -#### Suite: EdkWorkspace.proccessWorkspace - -Tests the public `proccessWorkspace()` API which wraps `_doProccessWorkspace` with `vscode.window.withProgress`. - -| # | Test | Description | -|---|------|-------------| -| 1 | proccessWorkspace runs without errors | Returns `true` and `platformName` is `'TestProcess'`. | -| 2 | proccessWorkspace populates defines and PCDs | `getDefinitions().size > 0` and `getAllPcds().size > 0`. | diff --git a/src/test/suite/aslParser.test.ts b/src/test/suite/aslParser.test.ts deleted file mode 100644 index a5411b7..0000000 --- a/src/test/suite/aslParser.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { AslParser } from '../../edkParser/aslParser'; -import { Edk2SymbolType } from '../../symbols/symbolsType'; -import { DebugLog } from '../../debugLog'; - -function ensureGlobals() { - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } -} - -async function parseAslFile(filename: string): Promise { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test', filename); - const uri = vscode.Uri.file(filePath); - const document = await vscode.workspace.openTextDocument(uri); - const parser = new AslParser(document); - await parser.parseFile(); - return parser; -} - -function symbolsOfType(parser: AslParser, type: Edk2SymbolType) { - return parser.symbolsList.filter(s => s.type === type); -} - -suite('ASL Parser – Symbol Extraction', () => { - - let parser: AslParser; - - suiteSetup(async function () { - this.timeout(10_000); - parser = await parseAslFile('testAslParsing.asl'); - }); - - suite('Blocks', () => { - test('Parses DefinitionBlock', () => { - const defs = symbolsOfType(parser, Edk2SymbolType.aslDefinitionBlock); - assert.ok(defs.length >= 1, 'Expected at least one DefinitionBlock'); - }); - - test('Parses External declarations', () => { - const externals = symbolsOfType(parser, Edk2SymbolType.aslExternal); - assert.ok(externals.length >= 2, `Expected >=2 externals, got ${externals.length}`); - }); - - test('Parses Scope blocks', () => { - const scopes = symbolsOfType(parser, Edk2SymbolType.aslScope); - assert.ok(scopes.length >= 2, `Expected >=2 scopes, got ${scopes.length}`); - }); - - test('Parses Device blocks', () => { - const devices = symbolsOfType(parser, Edk2SymbolType.aslDevice); - assert.ok(devices.length >= 2, `Expected >=2 devices, got ${devices.length}`); - }); - }); - - suite('Members', () => { - test('Parses Name declarations', () => { - const names = symbolsOfType(parser, Edk2SymbolType.aslName); - assert.ok(names.length >= 4, `Expected >=4 names, got ${names.length}`); - }); - - test('Parses Method blocks', () => { - const methods = symbolsOfType(parser, Edk2SymbolType.aslMethod); - assert.ok(methods.length >= 2, `Expected >=2 methods, got ${methods.length}`); - }); - - test('Parses OperationRegion declarations', () => { - const regions = symbolsOfType(parser, Edk2SymbolType.aslOpRegion); - assert.ok(regions.length >= 2, `Expected >=2 OperationRegions, got ${regions.length}`); - }); - - test('Parses Field declarations', () => { - const fields = symbolsOfType(parser, Edk2SymbolType.aslField); - assert.ok(fields.length >= 2, `Expected >=2 fields, got ${fields.length}`); - }); - }); - - suite('Tree Structure', () => { - test('DefinitionBlock has children', () => { - const defBlock = symbolsOfType(parser, Edk2SymbolType.aslDefinitionBlock); - assert.ok(defBlock.length > 0); - assert.ok(defBlock[0].children.length > 0, 'DefinitionBlock should have child symbols'); - }); - - test('Device contains Names as children', () => { - const devices = symbolsOfType(parser, Edk2SymbolType.aslDevice); - const tpm = devices.find(d => /TPM0/i.test(d.name)); - assert.ok(tpm, 'TPM0 device should exist'); - const childTypes = tpm!.children.map(c => (c as any).type); - assert.ok(childTypes.includes(Edk2SymbolType.aslName), 'TPM0 should contain a Name'); - }); - }); - - suite('Consistency', () => { - test('symbolsTree is not empty', () => { - assert.ok(parser.symbolsTree.length > 0); - }); - - test('symbolsList equals recursive tree count', () => { - function countNodes(nodes: vscode.DocumentSymbol[]): number { - let c = 0; - for (const n of nodes) { c++; c += countNodes(n.children); } - return c; - } - assert.strictEqual(parser.symbolsList.length, countNodes(parser.symbolsTree)); - }); - - test('Comments are not parsed as symbols', () => { - for (const s of parser.symbolsList) { - assert.ok(!s.name.startsWith('//'), `Symbol should not start with //: "${s.name}"`); - } - }); - }); -}); diff --git a/src/test/suite/decParser.test.ts b/src/test/suite/decParser.test.ts deleted file mode 100644 index d5c50b0..0000000 --- a/src/test/suite/decParser.test.ts +++ /dev/null @@ -1,144 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DecParser } from '../../edkParser/decParser'; -import { Edk2SymbolType } from '../../symbols/symbolsType'; -import { DebugLog } from '../../debugLog'; - -function ensureGlobals() { - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } -} - -async function parseDecFile(filename: string): Promise { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test', filename); - const uri = vscode.Uri.file(filePath); - const document = await vscode.workspace.openTextDocument(uri); - const parser = new DecParser(document); - await parser.parseFile(); - return parser; -} - -function symbolsOfType(parser: DecParser, type: Edk2SymbolType) { - return parser.symbolsList.filter(s => s.type === type); -} - -suite('DEC Parser – Symbol Extraction', () => { - - let parser: DecParser; - - suiteSetup(async function () { - this.timeout(10_000); - parser = await parseDecFile('testDecParsing.dec'); - }); - - suite('Sections', () => { - test('Parses [Defines] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.decSection); - const defines = sections.filter(s => /defines/i.test(s.name)); - assert.ok(defines.length >= 1, 'Expected at least one [Defines] section'); - }); - - test('Parses [Includes] sections (common + arch-specific)', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.decSection); - const incSections = sections.filter(s => /includes/i.test(s.name)); - assert.ok(incSections.length >= 2, `Expected >=2 Includes sections, got ${incSections.length}`); - }); - - test('Parses [LibraryClasses] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.decSection); - const libSections = sections.filter(s => /libraryclasses/i.test(s.name)); - assert.ok(libSections.length >= 1, 'Expected at least one [LibraryClasses] section'); - }); - - test('Parses [Guids] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.decSection); - const guidSections = sections.filter(s => /guids/i.test(s.name)); - assert.ok(guidSections.length >= 1, 'Expected at least one [Guids] section'); - }); - - test('Parses [Protocols] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.decSection); - const protoSections = sections.filter(s => /protocols/i.test(s.name)); - assert.ok(protoSections.length >= 1, 'Expected at least one [Protocols] section'); - }); - - test('Parses [Ppis] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.decSection); - const ppiSections = sections.filter(s => /ppis/i.test(s.name)); - assert.ok(ppiSections.length >= 1, 'Expected at least one [Ppis] section'); - }); - - test('Parses PCD sections', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.decSection); - const pcdSections = sections.filter(s => /pcds/i.test(s.name)); - assert.ok(pcdSections.length >= 2, `Expected >=2 PCD sections, got ${pcdSections.length}`); - }); - }); - - suite('Includes', () => { - test('Parses include directory entries', () => { - const includes = symbolsOfType(parser, Edk2SymbolType.decInclude); - assert.ok(includes.length >= 2, `Expected >=2 include paths, got ${includes.length}`); - }); - }); - - suite('Libraries', () => { - test('Parses library class entries', () => { - const libs = symbolsOfType(parser, Edk2SymbolType.decLibrary); - assert.ok(libs.length >= 2, `Expected >=2 library classes, got ${libs.length}`); - }); - }); - - suite('GUIDs', () => { - test('Parses GUID entries', () => { - const guids = symbolsOfType(parser, Edk2SymbolType.decGuid); - assert.ok(guids.length >= 1, `Expected >=1 GUID, got ${guids.length}`); - }); - }); - - suite('Protocols', () => { - test('Parses protocol entries', () => { - const protocols = symbolsOfType(parser, Edk2SymbolType.decProtocol); - assert.ok(protocols.length >= 2, `Expected >=2 protocols, got ${protocols.length}`); - }); - }); - - suite('PPIs', () => { - test('Parses PPI entries', () => { - const ppis = symbolsOfType(parser, Edk2SymbolType.decPpi); - assert.ok(ppis.length >= 1, `Expected >=1 PPI, got ${ppis.length}`); - }); - }); - - suite('PCDs', () => { - test('Parses PCD entries', () => { - const pcds = symbolsOfType(parser, Edk2SymbolType.decPcd); - assert.ok(pcds.length >= 2, `Expected >=2 PCDs, got ${pcds.length}`); - }); - }); - - suite('Consistency', () => { - test('symbolsTree is not empty', () => { - assert.ok(parser.symbolsTree.length > 0, 'symbolsTree should not be empty'); - }); - - test('symbolsList equals recursive tree count', () => { - function countNodes(nodes: vscode.DocumentSymbol[]): number { - let c = 0; - for (const n of nodes) { c++; c += countNodes(n.children); } - return c; - } - assert.strictEqual(parser.symbolsList.length, countNodes(parser.symbolsTree)); - }); - - test('Comments are not parsed as symbols', () => { - for (const s of parser.symbolsList) { - assert.ok(!s.name.startsWith('#'), `Symbol should not start with #: "${s.name}"`); - } - }); - }); -}); diff --git a/src/test/suite/dscParser.test.ts b/src/test/suite/dscParser.test.ts deleted file mode 100644 index ac45031..0000000 --- a/src/test/suite/dscParser.test.ts +++ /dev/null @@ -1,213 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DscParser } from '../../edkParser/dscParser'; -import { Edk2SymbolType } from '../../symbols/symbolsType'; -import { DebugLog } from '../../debugLog'; - -/** - * Ensure gDebugLog is initialised even when the extension does not activate - * (e.g. no workspace folders in the test environment). - */ -function ensureGlobals() { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } -} - -/** - * Helper: open a .dsc file from the test/ folder and parse it with DscParser. - * Returns the parser instance so callers can inspect symbolsList / symbolsTree. - */ -async function parseDscFile(filename: string): Promise { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test', filename); - const uri = vscode.Uri.file(filePath); - const document = await vscode.workspace.openTextDocument(uri); - const parser = new DscParser(document); - await parser.parseFile(); - return parser; -} - -/** Filter helper: return all symbols of a given type from the flat list. */ -function symbolsOfType(parser: DscParser, type: Edk2SymbolType) { - return parser.symbolsList.filter(s => s.type === type); -} - -suite('DSC Parser – Symbol Extraction', () => { - - let parser: DscParser; - - suiteSetup(async function () { - this.timeout(10_000); - parser = await parseDscFile('testDscParsing.dsc'); - }); - - suite('Sections', () => { - test('Parses [Defines] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.dscSection); - const defines = sections.filter(s => /defines/i.test(s.name)); - assert.ok(defines.length >= 1, 'Expected at least one [Defines] section'); - }); - - test('Parses [LibraryClasses] sections (common + arch-specific)', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.dscSection); - const libSections = sections.filter(s => /libraryclasses/i.test(s.name)); - assert.ok(libSections.length >= 2, `Expected >=2 LibraryClasses sections, got ${libSections.length}`); - }); - - test('Parses [Components] and [Components.X64] sections', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.dscSection); - const compSections = sections.filter(s => /components/i.test(s.name)); - assert.ok(compSections.length >= 2, `Expected >=2 Components sections, got ${compSections.length}`); - }); - - test('Parses [SkuIds] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.dscSection); - const sku = sections.filter(s => /skuids/i.test(s.name)); - assert.strictEqual(sku.length, 1, 'Expected exactly one [SkuIds] section'); - }); - - test('Parses [BuildOptions] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.dscBuildOptionsSection); - assert.ok(sections.length >= 1, 'Expected at least one [BuildOptions] section'); - }); - - test('Parses PCD sections (FixedAtBuild + DynamicDefault)', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.dscSection); - const pcdSections = sections.filter(s => /pcd/i.test(s.name)); - assert.ok(pcdSections.length >= 2, `Expected >=2 PCD sections, got ${pcdSections.length}`); - }); - }); - - suite('Defines', () => { - test('Parses DEFINE statements inside [Defines]', () => { - const defines = symbolsOfType(parser, Edk2SymbolType.dscDefine); - assert.ok(defines.length >= 3, `Expected >=3 defines, got ${defines.length}`); - }); - - test('DEFINE with empty value is still parsed', () => { - const defines = symbolsOfType(parser, Edk2SymbolType.dscDefine); - const emptyVar = defines.find(s => /EMPTY_VAR/i.test(s.name)); - assert.ok(emptyVar, 'EMPTY_VAR define should be parsed'); - }); - - test('Root-level DEFINE (outside section) is parsed', () => { - const defines = symbolsOfType(parser, Edk2SymbolType.dscDefine); - const rootDef = defines.find(s => /ROOT_DEFINE/i.test(s.name)); - assert.ok(rootDef, 'ROOT_DEFINE should be parsed as a root-level define'); - }); - }); - - suite('Libraries', () => { - test('Parses library class definitions', () => { - const libs = symbolsOfType(parser, Edk2SymbolType.dscLibraryDefinition); - assert.ok(libs.length >= 4, `Expected >=4 library definitions, got ${libs.length}`); - }); - - test('Library definition with extra whitespace around pipe is parsed', () => { - const libs = symbolsOfType(parser, Edk2SymbolType.dscLibraryDefinition); - const printLib = libs.find(s => /PrintLib/i.test(s.name)); - assert.ok(printLib, 'PrintLib (extra whitespace around |) should be parsed'); - }); - }); - - suite('Modules / Components', () => { - test('Parses simple .inf module references', () => { - const modules = symbolsOfType(parser, Edk2SymbolType.dscModuleDefinition); - assert.ok(modules.length >= 3, `Expected >=3 module definitions, got ${modules.length}`); - }); - - test('Module with sub-sections (curly braces) is parsed', () => { - const modules = symbolsOfType(parser, Edk2SymbolType.dscModuleDefinition); - const complex = modules.find(s => /ComplexModule/i.test(s.name)); - assert.ok(complex, 'ComplexModule.inf should be parsed as a module definition'); - assert.ok(complex!.children.length > 0, 'ComplexModule should have child sub-sections'); - }); - - test('Component sub-sections are parsed (, , )', () => { - const subSections = symbolsOfType(parser, Edk2SymbolType.dscComponentSubSection); - assert.ok(subSections.length >= 2, `Expected >=2 component sub-sections, got ${subSections.length}`); - }); - }); - - suite('PCDs', () => { - test('Parses PCD definitions', () => { - const pcds = symbolsOfType(parser, Edk2SymbolType.dscPcdDefinition); - assert.ok(pcds.length >= 3, `Expected >=3 PCD definitions, got ${pcds.length}`); - }); - }); - - suite('Build Options', () => { - test('Parses build option entries', () => { - const opts = symbolsOfType(parser, Edk2SymbolType.dscBuildOption); - assert.ok(opts.length >= 2, `Expected >=2 build options, got ${opts.length}`); - }); - }); - - suite('Includes', () => { - test('Parses !include directive', () => { - const includes = symbolsOfType(parser, Edk2SymbolType.dscInclude); - assert.ok(includes.length >= 1, 'Expected at least one !include directive'); - const inc = includes.find(s => /TestInclude/i.test(s.name)); - assert.ok(inc, 'TestInclude.dsc.inc should be found'); - }); - }); - - suite('Tree Structure', () => { - test('symbolsTree contains top-level section nodes', () => { - assert.ok(parser.symbolsTree.length > 0, 'symbolsTree should not be empty'); - for (const root of parser.symbolsTree) { - assert.ok( - root.type === Edk2SymbolType.dscSection || - root.type === Edk2SymbolType.dscBuildOptionsSection || - root.type === Edk2SymbolType.dscDefine || - root.type === Edk2SymbolType.dscInclude || - root.type === Edk2SymbolType.dscModuleDefinition || - root.type === Edk2SymbolType.dscLibraryDefinition || - root.type === Edk2SymbolType.dscPcdDefinition || - root.type === Edk2SymbolType.dscBuildOption || - root.type === Edk2SymbolType.unknown, - `Unexpected root symbol type: ${root.type}` - ); - } - }); - - test('Library definitions are children of their parent section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.dscSection); - const libSection = sections.find(s => /^\[?\s*libraryclasses\s*\]?$/i.test(s.name)); - if (libSection) { - const childLibs = libSection.children.filter( - c => (c as any).type === Edk2SymbolType.dscLibraryDefinition - ); - assert.ok(childLibs.length >= 3, `Expected >=3 library children in [LibraryClasses], got ${childLibs.length}`); - } - }); - }); - - suite('Consistency', () => { - test('symbolsList length equals total nodes across the tree', () => { - function countNodes(nodes: vscode.DocumentSymbol[]): number { - let count = 0; - for (const n of nodes) { - count++; - count += countNodes(n.children); - } - return count; - } - const treeCount = countNodes(parser.symbolsTree); - assert.strictEqual(parser.symbolsList.length, treeCount, - 'Flat symbolsList length should equal recursive tree node count'); - }); - - test('Comments are not parsed as symbols', () => { - const allNames = parser.symbolsList.map(s => s.name); - for (const name of allNames) { - assert.ok(!name.startsWith('#'), `Symbol name should not start with #: "${name}"`); - assert.ok(!name.startsWith('/*'), `Symbol name should not start with /*: "${name}"`); - } - }); - }); -}); diff --git a/src/test/suite/edkWorkspace.test.ts b/src/test/suite/edkWorkspace.test.ts deleted file mode 100644 index 043c1bd..0000000 --- a/src/test/suite/edkWorkspace.test.ts +++ /dev/null @@ -1,762 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DebugLog } from '../../debugLog'; -import { - SectionProperty, - SectionProperties, - InfDsc, - EdkWorkspaces, - EdkWorkspace, -} from '../../index/edkWorkspace'; - -/** - * Ensure gDebugLog is initialised even when the extension does not activate. - */ -function ensureGlobals() { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } -} - -function makeLoc(line: number = 0): vscode.Location { - return new vscode.Location( - vscode.Uri.file('d:/fake/test.dsc'), - new vscode.Position(line, 0) - ); -} - -// ─── SectionProperty ────────────────────────────────────────── - -suite('SectionProperty', () => { - test('constructor lowercases all fields', () => { - const prop = new SectionProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - assert.strictEqual(prop.sectionType, 'libraryclasses'); - assert.strictEqual(prop.arch, 'x64'); - assert.strictEqual(prop.moduleType, 'dxe_driver'); - }); - - test('constructor with already lowercase values', () => { - const prop = new SectionProperty('components', 'ia32', 'peim'); - assert.strictEqual(prop.sectionType, 'components'); - assert.strictEqual(prop.arch, 'ia32'); - assert.strictEqual(prop.moduleType, 'peim'); - }); -}); - -// ─── SectionProperties ──────────────────────────────────────── - -suite('SectionProperties', () => { - test('starts with empty properties', () => { - const sp = new SectionProperties(); - assert.strictEqual(sp.properties.length, 0); - }); - - test('addProperty adds correctly', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - assert.strictEqual(sp.properties.length, 1); - assert.strictEqual(sp.properties[0].sectionType, 'libraryclasses'); - }); - - test('addProperty multiple', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - sp.addProperty('Components', 'IA32', 'PEIM'); - assert.strictEqual(sp.properties.length, 2); - }); - - // ── compareArch ── - - test('compareArch returns true for matching arch', () => { - const sp1 = new SectionProperties(); - sp1.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - - const sp2 = new SectionProperties(); - sp2.addProperty('Components', 'X64', 'PEIM'); - - assert.strictEqual(sp1.compareArch(sp2), true); - }); - - test('compareArch returns false for different archs', () => { - const sp1 = new SectionProperties(); - sp1.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - - const sp2 = new SectionProperties(); - sp2.addProperty('Components', 'IA32', 'PEIM'); - - assert.strictEqual(sp1.compareArch(sp2), false); - }); - - // ── compareArchStr ── - - test('compareArchStr returns true for matching arch string', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - assert.strictEqual(sp.compareArchStr('X64'), true); - assert.strictEqual(sp.compareArchStr('x64'), true); - }); - - test('compareArchStr returns false for non-matching arch', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - assert.strictEqual(sp.compareArchStr('IA32'), false); - }); - - // ── compareLibSectionType ── - - test('compareLibSectionType returns true for matching section type', () => { - const sp1 = new SectionProperties(); - sp1.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - - const sp2 = new SectionProperties(); - sp2.addProperty('LibraryClasses', 'IA32', 'PEIM'); - - assert.strictEqual(sp1.compareLibSectionType(sp2), true); - }); - - test('compareLibSectionType returns false for different section types', () => { - const sp1 = new SectionProperties(); - sp1.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - - const sp2 = new SectionProperties(); - sp2.addProperty('Components', 'X64', 'DXE_DRIVER'); - - assert.strictEqual(sp1.compareLibSectionType(sp2), false); - }); - - // ── compareLibSectionTypeStr ── - - test('compareLibSectionTypeStr case-insensitive match', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - assert.strictEqual(sp.compareLibSectionTypeStr('LibraryClasses'), true); - assert.strictEqual(sp.compareLibSectionTypeStr('libraryclasses'), true); - assert.strictEqual(sp.compareLibSectionTypeStr('LIBRARYCLASSES'), true); - }); - - test('compareLibSectionTypeStr returns false for non-matching', () => { - const sp = new SectionProperties(); - sp.addProperty('Components', 'X64', 'DXE_DRIVER'); - assert.strictEqual(sp.compareLibSectionTypeStr('LibraryClasses'), false); - }); - - // ── compareModuleType ── - - test('compareModuleType returns true for matching module type', () => { - const sp1 = new SectionProperties(); - sp1.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - - const sp2 = new SectionProperties(); - sp2.addProperty('Components', 'IA32', 'DXE_DRIVER'); - - assert.strictEqual(sp1.compareModuleType(sp2), true); - }); - - test('compareModuleType returns false for different module types', () => { - const sp1 = new SectionProperties(); - sp1.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - - const sp2 = new SectionProperties(); - sp2.addProperty('LibraryClasses', 'X64', 'PEIM'); - - assert.strictEqual(sp1.compareModuleType(sp2), false); - }); - - // ── compareModuleTypeStr ── - - test('compareModuleTypeStr case-insensitive', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - assert.strictEqual(sp.compareModuleTypeStr('DXE_DRIVER'), true); - assert.strictEqual(sp.compareModuleTypeStr('dxe_driver'), true); - }); - - test('compareModuleTypeStr returns false for non-matching', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - assert.strictEqual(sp.compareModuleTypeStr('PEIM'), false); - }); - - // ── toString ── - - test('toString returns comma-separated properties', () => { - const sp = new SectionProperties(); - sp.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - sp.addProperty('Components', 'IA32', 'PEIM'); - const str = sp.toString(); - assert.ok(str.includes(','), 'should contain comma separator'); - }); - - // ── multi-property matching ── - - test('compareArch matches any combination', () => { - const sp1 = new SectionProperties(); - sp1.addProperty('LibraryClasses', 'X64', 'DXE_DRIVER'); - sp1.addProperty('LibraryClasses', 'IA32', 'DXE_DRIVER'); - - const sp2 = new SectionProperties(); - sp2.addProperty('Components', 'IA32', 'PEIM'); - - assert.strictEqual(sp1.compareArch(sp2), true); - }); -}); - -// ─── InfDsc ─────────────────────────────────────────────────── - -suite('InfDsc', () => { - test('constructor with section parent sets sectionProperties', () => { - ensureGlobals(); - const loc = makeLoc(10); - const inf = new InfDsc( - 'MdePkg/Library/BaseLib/BaseLib.inf', - loc, - 'Components.X64', - 'MdePkg/Library/BaseLib/BaseLib.inf' - ); - assert.strictEqual(inf.parent, undefined, 'section parent should set parent to undefined'); - assert.ok(inf.sectionProperties.properties.length > 0, 'should have section properties'); - assert.strictEqual(inf.sectionProperties.properties[0].sectionType, 'components'); - assert.strictEqual(inf.sectionProperties.properties[0].arch, 'x64'); - }); - - test('constructor with INF parent sets parent path', () => { - ensureGlobals(); - const loc = makeLoc(5); - const inf = new InfDsc( - 'MdePkg/Library/BaseLib/BaseLib.inf', - loc, - 'SomeModule/Module.inf', - 'SomeLib|MdePkg/Library/BaseLib/BaseLib.inf' - ); - assert.ok(inf.parent !== undefined, 'INF parent should set parent path'); - assert.ok(inf.parent!.includes('Module.inf')); - assert.strictEqual(inf.sectionProperties.properties.length, 0, 'INF parent should not set section properties'); - }); - - test('constructor normalizes path separators', () => { - ensureGlobals(); - const loc = makeLoc(); - const inf = new InfDsc( - 'MdePkg/Library/BaseLib/BaseLib.inf', - loc, - 'Components.common', - 'line text' - ); - // path.sep on Windows is \\, on Linux / - assert.ok(!inf.path.includes('/') || path.sep === '/', 'forward slashes should be normalized to path.sep'); - }); - - test('constructor with multi-section parent', () => { - ensureGlobals(); - const loc = makeLoc(); - const inf = new InfDsc( - 'Pkg/Lib.inf', - loc, - 'LibraryClasses.X64.DXE_DRIVER,LibraryClasses.IA32.PEIM', - 'SomeLib|Pkg/Lib.inf' - ); - assert.strictEqual(inf.parent, undefined); - assert.strictEqual(inf.sectionProperties.properties.length, 2); - assert.strictEqual(inf.sectionProperties.properties[0].arch, 'x64'); - assert.strictEqual(inf.sectionProperties.properties[0].moduleType, 'dxe_driver'); - assert.strictEqual(inf.sectionProperties.properties[1].arch, 'ia32'); - assert.strictEqual(inf.sectionProperties.properties[1].moduleType, 'peim'); - }); - - test('constructor with section missing arch defaults to common', () => { - ensureGlobals(); - const loc = makeLoc(); - const inf = new InfDsc( - 'Pkg/Lib.inf', - loc, - 'libraryclasses', - 'SomeLib|Pkg/Lib.inf' - ); - assert.strictEqual(inf.sectionProperties.properties[0].sectionType, 'libraryclasses'); - assert.strictEqual(inf.sectionProperties.properties[0].arch, 'common'); - assert.strictEqual(inf.sectionProperties.properties[0].moduleType, 'common'); - }); - - test('getModuleTypeStr returns comma-separated module types', () => { - ensureGlobals(); - const loc = makeLoc(); - const inf = new InfDsc( - 'Pkg/Lib.inf', - loc, - 'LibraryClasses.X64.DXE_DRIVER,LibraryClasses.IA32.PEIM', - 'SomeLib|Pkg/Lib.inf' - ); - const moduleTypes = inf.getModuleTypeStr(); - assert.ok(moduleTypes.includes('dxe_driver')); - assert.ok(moduleTypes.includes('peim')); - assert.ok(moduleTypes.includes(',')); - }); - - test('getModuleTypeStr single property', () => { - ensureGlobals(); - const loc = makeLoc(); - const inf = new InfDsc( - 'Pkg/Mod.inf', - loc, - 'Components.X64', - 'Pkg/Mod.inf' - ); - const moduleTypes = inf.getModuleTypeStr(); - assert.strictEqual(moduleTypes, 'common'); - }); - - test('toString includes path and line number', () => { - ensureGlobals(); - const loc = makeLoc(42); - const inf = new InfDsc( - 'Pkg/Mod.inf', - loc, - 'Components.X64', - 'Pkg/Mod.inf' - ); - const str = inf.toString(); - assert.ok(str.includes('42'), 'toString should include line number'); - }); - - test('text property stores original line', () => { - ensureGlobals(); - const loc = makeLoc(); - const inf = new InfDsc( - 'Pkg/Lib.inf', - loc, - 'LibraryClasses.common', - 'BaseLib|MdePkg/Library/BaseLib/BaseLib.inf' - ); - assert.strictEqual(inf.text, 'BaseLib|MdePkg/Library/BaseLib/BaseLib.inf'); - }); - - test('location is preserved', () => { - ensureGlobals(); - const loc = makeLoc(99); - const inf = new InfDsc( - 'Pkg/Lib.inf', - loc, - 'Components', - 'line' - ); - assert.strictEqual(inf.location.range.start.line, 99); - }); -}); - -// ─── EdkWorkspaces ──────────────────────────────────────────── - -suite('EdkWorkspaces', () => { - test('isConfigured returns false when no workspaces', () => { - const ws = new EdkWorkspaces(); - assert.strictEqual(ws.isConfigured(), false); - }); - - test('isConfigured returns true after adding a workspace', async () => { - ensureGlobals(); - const ws = new EdkWorkspaces(); - // Create a minimal mock document for the constructor - const filePath = path.resolve(__dirname, '../../../test/testDscParsing.dsc'); - const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath)); - const edkWs = new EdkWorkspace(doc); - ws.workspaces = [edkWs]; - assert.strictEqual(ws.isConfigured(), true); - }); - - test('getInstance returns singleton', () => { - const inst1 = EdkWorkspaces.getInstance(); - const inst2 = EdkWorkspaces.getInstance(); - assert.strictEqual(inst1, inst2); - }); - - test('isFileInUse returns undefined when no workspaces', async () => { - const ws = new EdkWorkspaces(); - const result = await ws.isFileInUse(vscode.Uri.file('d:/fake/file.dsc')); - assert.strictEqual(result, undefined); - }); - - test('getWorkspace returns empty array when no workspaces', async () => { - const ws = new EdkWorkspaces(); - const result = await ws.getWorkspace(vscode.Uri.file('d:/fake/file.dsc')); - assert.strictEqual(result.length, 0); - }); - - test('getDefinition returns undefined when no workspaces', async () => { - const ws = new EdkWorkspaces(); - const result = await ws.getDefinition(vscode.Uri.file('d:/fake/file.dsc'), 'SOME_VAR'); - assert.strictEqual(result, undefined); - }); - - test('replaceDefines returns original text when no workspaces', async () => { - const ws = new EdkWorkspaces(); - const result = await ws.replaceDefines(vscode.Uri.file('d:/fake/file.dsc'), '$(MY_VAR)/path'); - assert.strictEqual(result, '$(MY_VAR)/path'); - }); - - test('getLib returns empty array when no workspaces', async () => { - const ws = new EdkWorkspaces(); - const loc = new vscode.Location( - vscode.Uri.file('d:/fake/file.dsc'), - new vscode.Position(0, 0) - ); - const result = await ws.getLib(loc); - assert.strictEqual(result.length, 0); - }); -}); - -// ─── EdkWorkspace ───────────────────────────────────────────── - -suite('EdkWorkspace', () => { - let workspace: EdkWorkspace; - - suiteSetup(async () => { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test/testDscParsing.dsc'); - const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath)); - workspace = new EdkWorkspace(doc); - }); - - // ── Constructor ── - - test('constructor sets mainDsc from document', () => { - assert.ok(workspace.mainDsc.fsPath.endsWith('testDscParsing.dsc')); - }); - - test('constructor generates a numeric id', () => { - assert.strictEqual(typeof workspace.id, 'number'); - assert.ok(workspace.id > 0); - }); - - test('platformName starts as undefined', () => { - assert.strictEqual(workspace.platformName, undefined); - }); - - test('flashDefinitionDocument starts as undefined', () => { - assert.strictEqual(workspace.flashDefinitionDocument, undefined); - }); - - // ── Lists ── - - test('filesLibraries starts empty', () => { - assert.strictEqual(workspace.filesLibraries.length, 0); - }); - - test('filesModules starts empty', () => { - assert.strictEqual(workspace.filesModules.length, 0); - }); - - test('dscList is initially empty', () => { - assert.strictEqual(workspace.dscList().length, 0); - }); - - test('fdfList is initially empty', () => { - assert.strictEqual(workspace.fdfList().length, 0); - }); - - test('getFilesList aggregates all file lists', () => { - assert.ok(Array.isArray(workspace.getFilesList())); - }); - - test('includeTree starts empty', () => { - assert.strictEqual(workspace.includeTree.length, 0); - }); - - // ── Definitions (no processing) ── - - test('getDefinitions returns a Map', () => { - const defs = workspace.getDefinitions(); - assert.ok(defs instanceof Map); - }); - - test('getDefinition returns undefined for unknown key', () => { - assert.strictEqual(workspace.getDefinition('NON_EXISTENT'), undefined); - }); - - test('getDefinitionLocation returns undefined for unknown key', () => { - assert.strictEqual(workspace.getDefinitionLocation('NON_EXISTENT'), undefined); - }); - - test('replaceDefine passes through text with no defines', () => { - const result = workspace.replaceDefine('$(UNKNOWN_VAR)/path'); - assert.strictEqual(result, '$(UNKNOWN_VAR)/path'); - }); - - // ── PCDs ── - - test('getPcds returns undefined for unknown namespace', () => { - assert.strictEqual(workspace.getPcds('gUnknownPkg'), undefined); - }); - - test('getAllPcds returns a Map', () => { - const pcds = workspace.getAllPcds(); - assert.ok(pcds instanceof Map); - }); - - // ── Library / Module management ── - - test('filesLibraries can be set', () => { - const loc = makeLoc(); - const lib = new InfDsc('Pkg/Lib.inf', loc, 'LibraryClasses.common', 'BaseLib|Pkg/Lib.inf'); - workspace.filesLibraries = [lib]; - assert.strictEqual(workspace.filesLibraries.length, 1); - workspace.filesLibraries = []; // reset - }); - - test('filesModules can be set', () => { - const loc = makeLoc(); - const mod = new InfDsc('Pkg/Mod.inf', loc, 'Components.X64', 'Pkg/Mod.inf'); - workspace.filesModules = [mod]; - assert.strictEqual(workspace.filesModules.length, 1); - workspace.filesModules = []; // reset - }); - - test('getFilesList includes libraries and modules', () => { - const loc = makeLoc(); - workspace.filesLibraries = [new InfDsc('Pkg/Lib.inf', loc, 'LibraryClasses', 'Lib|Pkg/Lib.inf')]; - workspace.filesModules = [new InfDsc('Pkg/Mod.inf', loc, 'Components', 'Pkg/Mod.inf')]; - const list = workspace.getFilesList(); - assert.ok(list.length >= 2, 'should include at least library and module paths'); - workspace.filesLibraries = []; - workspace.filesModules = []; - }); - - // ── filesDsc / filesFdf sets ── - - test('filesDsc can be set and read', async () => { - const filePath = path.resolve(__dirname, '../../../test/testDscParsing.dsc'); - const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath)); - workspace.filesDsc = new Set([doc]); - assert.strictEqual(workspace.filesDsc.size, 1); - assert.strictEqual(workspace.dscList().length, 1); - workspace.filesDsc = new Set(); - }); - - test('filesFdf can be set and read', async () => { - const filePath = path.resolve(__dirname, '../../../test/testFdfParsing.fdf'); - const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath)); - workspace.filesFdf = new Set([doc]); - assert.strictEqual(workspace.filesFdf.size, 1); - assert.strictEqual(workspace.fdfList().length, 1); - workspace.filesFdf = new Set(); - }); - - // ── getLib ── - - test('getLib returns undefined when no matching library', async () => { - const loc = new vscode.Location( - vscode.Uri.file('d:/nonexistent/file.dsc'), - new vscode.Position(999, 0) - ); - const result = await workspace.getLib(loc); - assert.strictEqual(result, undefined); - }); - - test('getLib finds matching library by location', async () => { - const uri = vscode.Uri.file('d:/fake/platform.dsc'); - const loc = new vscode.Location(uri, new vscode.Position(10, 0)); - const lib = new InfDsc('Pkg/Lib.inf', loc, 'LibraryClasses.common', 'BaseLib|Pkg/Lib.inf'); - workspace.filesLibraries = [lib]; - - const result = await workspace.getLib(loc); - assert.ok(result !== undefined, 'should find the library'); - assert.strictEqual(result!.path, lib.path); - workspace.filesLibraries = []; - }); -}); - -// ─── EdkWorkspace.evaluateExpression ────────────────────────── - -suite('EdkWorkspace.evaluateExpression', () => { - let workspace: EdkWorkspace; - - suiteSetup(async () => { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test/testDscParsing.dsc'); - const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath)); - workspace = new EdkWorkspace(doc); - }); - - // ── Boolean literals ── - - test('TRUE evaluates to true', () => { - assert.strictEqual(workspace.evaluateExpression('TRUE'), true); - }); - - test('FALSE evaluates to false', () => { - assert.strictEqual(workspace.evaluateExpression('FALSE'), false); - }); - - test('true/false case-insensitive', () => { - assert.strictEqual(workspace.evaluateExpression('true'), true); - assert.strictEqual(workspace.evaluateExpression('True'), true); - assert.strictEqual(workspace.evaluateExpression('false'), false); - }); - - // ── Numeric literals ── - - test('numeric 1 is truthy', () => { - assert.strictEqual(workspace.evaluateExpression('1'), 1); - }); - - test('numeric 0 is falsy', () => { - assert.strictEqual(workspace.evaluateExpression('0'), 0); - }); - - // ── Equality operators ── - - test('== with matching strings', () => { - assert.strictEqual(workspace.evaluateExpression('"hello" == "hello"'), true); - }); - - test('== with non-matching strings', () => { - assert.strictEqual(workspace.evaluateExpression('"hello" == "world"'), false); - }); - - test('!= with different strings', () => { - assert.strictEqual(workspace.evaluateExpression('"hello" != "world"'), true); - }); - - test('!= with same strings', () => { - assert.strictEqual(workspace.evaluateExpression('"hello" != "hello"'), false); - }); - - test('EQ operator', () => { - assert.strictEqual(workspace.evaluateExpression('"a" EQ "a"'), true); - }); - - test('NE operator', () => { - assert.strictEqual(workspace.evaluateExpression('"a" NE "b"'), true); - }); - - // ── Logical operators ── - - test('AND with both true', () => { - assert.strictEqual(workspace.evaluateExpression('TRUE AND TRUE'), true); - }); - - test('AND with one false', () => { - assert.strictEqual(workspace.evaluateExpression('TRUE AND FALSE'), false); - }); - - test('OR with one true', () => { - assert.strictEqual(workspace.evaluateExpression('FALSE OR TRUE'), true); - }); - - test('OR with both false', () => { - assert.strictEqual(workspace.evaluateExpression('FALSE OR FALSE'), false); - }); - - test('&& operator', () => { - assert.strictEqual(workspace.evaluateExpression('TRUE && TRUE'), true); - }); - - test('|| operator', () => { - assert.strictEqual(workspace.evaluateExpression('FALSE || TRUE'), true); - }); - - // ── NOT operator ── - - test('NOT TRUE evaluates to false', () => { - // NOT is a unary operator that uses stack pop for y, x is undefined - const result = workspace.evaluateExpression('NOT TRUE'); - assert.strictEqual(result, false); - }); - - test('NOT FALSE evaluates to true', () => { - const result = workspace.evaluateExpression('NOT FALSE'); - // NOT inverts the value - assert.ok(result, 'NOT FALSE should be truthy'); - }); - - // ── Arithmetic ── - - test('addition', () => { - assert.strictEqual(workspace.evaluateExpression('3 + 2'), 5); - }); - - test('subtraction', () => { - assert.strictEqual(workspace.evaluateExpression('5 - 2'), 3); - }); - - test('multiplication', () => { - assert.strictEqual(workspace.evaluateExpression('3 * 4'), 12); - }); - - test('division', () => { - assert.strictEqual(workspace.evaluateExpression('10 / 2'), 5); - }); - - test('modulus', () => { - assert.strictEqual(workspace.evaluateExpression('10 % 3'), 1); - }); - - // ── Comparison ── - - test('greater than', () => { - assert.strictEqual(workspace.evaluateExpression('5 > 3'), true); - }); - - test('less than', () => { - assert.strictEqual(workspace.evaluateExpression('3 > 5'), false); - }); - - test('greater or equal', () => { - assert.strictEqual(workspace.evaluateExpression('5 >= 5'), true); - }); - - test('less or equal', () => { - assert.strictEqual(workspace.evaluateExpression('3 <= 5'), true); - }); - - // ── Parentheses ── - - test('parentheses group expressions', () => { - assert.strictEqual(workspace.evaluateExpression('(TRUE OR FALSE) AND TRUE'), true); - }); - - test('nested parentheses', () => { - assert.strictEqual(workspace.evaluateExpression('((1 + 2) * 3)'), 9); - }); - - test('unbalanced parentheses throw', () => { - assert.throws(() => { - workspace.evaluateExpression('(TRUE AND FALSE'); - }); - }); - - // ── IN operator ── - - test('IN operator with match', () => { - assert.strictEqual(workspace.evaluateExpression('"X64" IN "X64 IA32 ARM"'), true); - }); - - test('IN operator without match', () => { - assert.strictEqual(workspace.evaluateExpression('"AARCH64" IN "X64 IA32 ARM"'), false); - }); - - // ── Undefined variables (???) ── - - test('undefined variable evaluates to false', () => { - // The expression evaluator replaces "???" with FALSE - assert.strictEqual(workspace.evaluateExpression('"???"'), false); - }); - - // ── String without quotes treated as string ── - - test('bare word is treated as quoted string', () => { - const result = workspace.evaluateExpression('hello == "hello"'); - assert.strictEqual(result, true); - }); - - // ── Complex expressions ── - - test('complex: (1 + 2) > 2 AND TRUE', () => { - assert.strictEqual(workspace.evaluateExpression('(1 + 2) > 2 AND TRUE'), true); - }); - - test('complex: FALSE OR (5 == 5)', () => { - assert.strictEqual(workspace.evaluateExpression('FALSE OR (5 == 5)'), true); - }); -}); diff --git a/src/test/suite/edkWorkspaceProcess.test.ts b/src/test/suite/edkWorkspaceProcess.test.ts deleted file mode 100644 index 37f99f0..0000000 --- a/src/test/suite/edkWorkspaceProcess.test.ts +++ /dev/null @@ -1,422 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { DebugLog } from '../../debugLog'; -import { ConfigAgent } from '../../configuration'; -import { DiagnosticManager } from '../../diagnostics'; -import { EdkWorkspace, InfDsc } from '../../index/edkWorkspace'; -import { PathFind } from '../../pathfind'; - -/** - * Ensure all globals required by EdkWorkspace processing are available. - * Stubs status bar, tree provider, path finder, config agent, and - * diagnostics so the private _processDocument / _doProccessWorkspace - * can run in a test environment. - */ -function ensureProcessingGlobals() { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } - if (!ext.gWorkspacePath) { - ext.gWorkspacePath = path.resolve(__dirname, '../../../'); - } - if (!ext.gConfigAgent) { - ext.gConfigAgent = new ConfigAgent(); - } - if (!ext.gPathFind) { - ext.gPathFind = new PathFind(); - } - // Stub edkWorkspaceTreeProvider.refresh() - if (!ext.edkWorkspaceTreeProvider) { - ext.edkWorkspaceTreeProvider = { refresh() {} }; - } - - // Initialize DiagnosticManager (creates diagnosticsCollection) - DiagnosticManager.getInstance(); - - // Stub edkStatusBar functions that reference myStatusBarItem - // eslint-disable-next-line @typescript-eslint/no-var-requires - const statusBar = require('../../statusBar'); - if (!statusBar.myStatusBarItem) { - statusBar.myStatusBarItem = { - text: '', - tooltip: '', - show() {}, - hide() {}, - backgroundColor: undefined, - command: undefined, - }; - } -} - -/** - * Open a DSC file from the test/ folder and create an EdkWorkspace from it. - */ -async function openDscDocument(filename: string): Promise { - const filePath = path.resolve(__dirname, '../../../test', filename); - const uri = vscode.Uri.file(filePath); - return vscode.workspace.openTextDocument(uri); -} - -// ═══════════════════════════════════════════════════════════════ -// _processDocument tests -// ═══════════════════════════════════════════════════════════════ - -suite('EdkWorkspace._processDocument', () => { - let workspace: EdkWorkspace; - let doc: vscode.TextDocument; - - suiteSetup(async function () { - this.timeout(15_000); - ensureProcessingGlobals(); - doc = await openDscDocument('testDscProcess.dsc'); - workspace = new EdkWorkspace(doc); - // Call private method directly - await (workspace as any)._processDocument(doc, 'DSC'); - }); - - suite('Document Registration', () => { - test('Adds document to filesDsc', () => { - const dscPaths = workspace.dscList(); - assert.ok(dscPaths.length >= 1, 'filesDsc should contain at least the main document'); - assert.ok( - dscPaths.some(p => p.endsWith('testDscProcess.dsc')), - 'filesDsc should include testDscProcess.dsc' - ); - }); - - test('isDocumentInIndex returns true after processing', () => { - assert.strictEqual( - (workspace as any).isDocumentInIndex(doc), - true, - 'Document should be in the index after processing' - ); - }); - - test('Processing same document twice is a no-op', async () => { - const sizeBefore = workspace.dscList().length; - await (workspace as any)._processDocument(doc, 'DSC'); - assert.strictEqual(workspace.dscList().length, sizeBefore, 'Should not re-add'); - }); - }); - - suite('Defines Extraction', () => { - test('Extracts PLATFORM_NAME from [Defines]', () => { - assert.strictEqual(workspace.getDefinition('PLATFORM_NAME'), 'TestProcess'); - }); - - test('Extracts PLATFORM_GUID', () => { - assert.strictEqual( - workspace.getDefinition('PLATFORM_GUID'), - '11111111-2222-3333-4444-555555555555' - ); - }); - - test('Extracts DEFINE MY_FLAG', () => { - assert.strictEqual(workspace.getDefinition('MY_FLAG'), 'TRUE'); - }); - - test('Extracts DEFINE with empty value', () => { - const val = workspace.getDefinition('EMPTY_DEF'); - assert.ok(val !== undefined, 'EMPTY_DEF should be defined'); - assert.strictEqual(val!.trim(), ''); - }); - - test('Extracts root-level DEFINE', () => { - assert.strictEqual(workspace.getDefinition('ROOT_DEF'), 'RootValue'); - }); - - test('getDefinitionLocation returns a Location for known define', () => { - const loc = workspace.getDefinitionLocation('PLATFORM_NAME'); - assert.ok(loc !== undefined, 'Should have a location'); - assert.ok(loc!.uri.fsPath.endsWith('testDscProcess.dsc')); - }); - - test('getDefinitions returns all defines as a Map', () => { - const defs = workspace.getDefinitions(); - assert.ok(defs instanceof Map); - assert.ok(defs.size >= 5, `Expected >=5 defines, got ${defs.size}`); - }); - }); - - suite('Define Variable Substitution', () => { - test('DERIVED define has $(BASE) resolved', () => { - const val = workspace.getDefinition('DERIVED'); - assert.strictEqual(val, 'HelloWorld', 'DERIVED should be resolved to HelloWorld'); - }); - - test('replaceDefine substitutes known variables', () => { - const result = workspace.replaceDefine('$(MY_FLAG)'); - assert.strictEqual(result, 'TRUE'); - }); - - test('replaceDefine leaves unknown variables untouched', () => { - const result = workspace.replaceDefine('$(TOTALLY_UNKNOWN)'); - assert.strictEqual(result, '$(TOTALLY_UNKNOWN)'); - }); - }); - - suite('PCD Extraction', () => { - test('Extracts PCDs in gTestPkg namespace', () => { - const pcds = workspace.getPcds('gTestPkg'); - assert.ok(pcds !== undefined, 'gTestPkg PCDs should exist'); - }); - - test('PcdTestMask has correct value', () => { - const pcds = workspace.getPcds('gTestPkg'); - const pcd = pcds?.get('PcdTestMask'); - assert.ok(pcd !== undefined, 'PcdTestMask should exist'); - assert.strictEqual(pcd!.value, '0x2F'); - }); - - test('PcdBootTimeout from DynamicDefault', () => { - const pcds = workspace.getPcds('gTestPkg'); - const pcd = pcds?.get('PcdBootTimeout'); - assert.ok(pcd !== undefined, 'PcdBootTimeout should exist'); - assert.strictEqual(pcd!.value, '5'); - }); - - test('PCD with L"string" value strips L prefix', () => { - const pcds = workspace.getPcds('gTestPkg'); - const pcd = pcds?.get('PcdStringVal'); - assert.ok(pcd !== undefined, 'PcdStringVal should exist'); - assert.ok(pcd!.value.startsWith('"'), 'Value should start with " after L is stripped'); - }); - - test('PCD has location information', () => { - const pcds = workspace.getPcds('gTestPkg'); - const pcd = pcds?.get('PcdTestMask'); - assert.ok(pcd!.position.uri.fsPath.endsWith('testDscProcess.dsc')); - }); - - test('getAllPcds returns all namespaces', () => { - const all = workspace.getAllPcds(); - assert.ok(all.has('gTestPkg'), 'Should have gTestPkg namespace'); - }); - }); - - suite('Conditional Processing', () => { - test('!if TRUE branch: COND_TAKEN is defined', () => { - assert.strictEqual(workspace.getDefinition('COND_TAKEN'), 'IfTrueValue'); - }); - - test('!if TRUE branch: else branch not taken', () => { - // COND_TAKEN should NOT be IfFalseValue - assert.notStrictEqual(workspace.getDefinition('COND_TAKEN'), 'IfFalseValue'); - }); - - test('!if FALSE: else branch taken, COND_ELSE is defined', () => { - assert.strictEqual(workspace.getDefinition('COND_ELSE'), 'ElseValue'); - }); - - test('!if FALSE: if branch not taken, COND_FALSE_IF not defined', () => { - assert.strictEqual(workspace.getDefinition('COND_FALSE_IF'), undefined); - }); - - test('Nested conditionals: outer TRUE inner FALSE -> INNER_ELSE defined', () => { - assert.strictEqual(workspace.getDefinition('OUTER_TRUE'), 'OuterOk'); - assert.strictEqual(workspace.getDefinition('INNER_ELSE'), 'InnerElseOk'); - }); - - test('Nested conditionals: INNER_FALSE not defined', () => { - assert.strictEqual(workspace.getDefinition('INNER_FALSE'), undefined); - }); - - test('!ifdef on existing variable takes the branch', () => { - assert.strictEqual(workspace.getDefinition('IFDEF_TAKEN'), 'yes'); - }); - - test('!ifndef on undefined variable takes the branch', () => { - assert.strictEqual(workspace.getDefinition('IFNDEF_TAKEN'), 'yes'); - }); - - test('COND_A before conditional is still defined', () => { - assert.strictEqual(workspace.getDefinition('COND_A'), 'BeforeIf'); - }); - }); - - suite('Library and Module References', () => { - test('Libraries are collected (even if paths unresolved)', () => { - // Libraries are added even when gPathFind.findPath returns empty - assert.ok(workspace.filesLibraries.length >= 2, - `Expected >=2 library refs, got ${workspace.filesLibraries.length}`); - }); - - test('Modules are collected (even if paths unresolved)', () => { - assert.ok(workspace.filesModules.length >= 2, - `Expected >=2 module refs, got ${workspace.filesModules.length}`); - }); - - test('Library InfDsc has correct section properties', () => { - const lib = workspace.filesLibraries.find(l => l.path.includes('BaseLib')); - assert.ok(lib !== undefined, 'BaseLib should be in libraries'); - assert.ok(lib!.sectionProperties.properties.length > 0); - }); - - test('Module InfDsc preserves location', () => { - const mod = workspace.filesModules[0]; - assert.ok(mod.location.uri.fsPath.endsWith('testDscProcess.dsc')); - }); - }); - - suite('Grayout Ranges', () => { - test('parsedDocuments has entry for processed document', () => { - const ranges = (workspace as any).parsedDocuments.get(doc.uri.fsPath); - assert.ok(ranges !== undefined, 'Should have grayout entry'); - }); - - test('Grayout ranges exist for inactive conditional blocks', () => { - const ranges: vscode.Range[] = (workspace as any).parsedDocuments.get(doc.uri.fsPath); - // The !if FALSE ... !else block should generate at least one grayout range - assert.ok(ranges.length >= 1, - `Expected >=1 grayout ranges, got ${ranges.length}`); - }); - }); - - suite('Comment Stripping', () => { - test('stripComment removes line comments', () => { - const result = (workspace as any).stripComment('DEFINE X = 1 # comment'); - assert.strictEqual(result, 'DEFINE X = 1'); - }); - - test('stripComment preserves hash inside quotes', () => { - const result = (workspace as any).stripComment('DEFINE X = "value#with#hash"'); - assert.strictEqual(result, 'DEFINE X = "value#with#hash"'); - }); - - test('stripComment trims whitespace', () => { - const result = (workspace as any).stripComment(' some text '); - assert.strictEqual(result, 'some text'); - }); - - test('stripComment returns empty for comment-only line', () => { - const result = (workspace as any).stripComment('# just a comment'); - assert.strictEqual(result, ''); - }); - }); -}); - -// ═══════════════════════════════════════════════════════════════ -// _doProccessWorkspace tests -// ═══════════════════════════════════════════════════════════════ - -suite('EdkWorkspace._doProccessWorkspace', () => { - let workspace: EdkWorkspace; - - suiteSetup(async function () { - this.timeout(15_000); - ensureProcessingGlobals(); - const doc = await openDscDocument('testDscProcess.dsc'); - workspace = new EdkWorkspace(doc); - const result = await (workspace as any)._doProccessWorkspace(); - assert.ok(result === true, '_doProccessWorkspace should return true'); - }); - - suite('Workspace Initialization', () => { - test('platformName is populated from PLATFORM_NAME define', () => { - assert.strictEqual(workspace.platformName, 'TestProcess'); - }); - - test('workInProgress is false after completion', () => { - assert.strictEqual((workspace as any).workInProgress, false); - }); - - test('processComplete is true after completion', () => { - assert.strictEqual((workspace as any).processComplete, true); - }); - }); - - suite('State Reset', () => { - test('Running again resets and re-processes', async () => { - // First run already done in suiteSetup. Reset workInProgress flag - // by accessing the internal state directly (it was set to false). - const result = await (workspace as any)._doProccessWorkspace(); - assert.ok(result === true, 'Second run should succeed'); - assert.strictEqual(workspace.platformName, 'TestProcess'); - }); - - test('Returns false if already in progress', async () => { - (workspace as any).workInProgress = true; - const result = await (workspace as any)._doProccessWorkspace(); - assert.strictEqual(result, false, 'Should return false when workInProgress'); - (workspace as any).workInProgress = false; - }); - }); - - suite('Defines After Full Processing', () => { - test('All defines from [Defines] section are available', () => { - const defs = workspace.getDefinitions(); - assert.ok(defs.has('PLATFORM_NAME')); - assert.ok(defs.has('MY_FLAG')); - assert.ok(defs.has('MY_PATH')); - }); - - test('Conditional defines are correctly resolved', () => { - assert.strictEqual(workspace.getDefinition('COND_TAKEN'), 'IfTrueValue'); - assert.strictEqual(workspace.getDefinition('COND_ELSE'), 'ElseValue'); - }); - - test('replaceDefine works after processing', () => { - const result = workspace.replaceDefine('$(PLATFORM_NAME)'); - assert.strictEqual(result, 'TestProcess'); - }); - }); - - suite('PCDs After Full Processing', () => { - test('PCDs are available after processing', () => { - const pcds = workspace.getPcds('gTestPkg'); - assert.ok(pcds !== undefined); - assert.ok(pcds!.size >= 3, `Expected >=3 PCDs, got ${pcds!.size}`); - }); - }); - - suite('File Lists After Full Processing', () => { - test('dscList contains the main document', () => { - const list = workspace.dscList(); - assert.ok(list.length >= 1, 'dscList should have at least 1 entry'); - assert.ok(list.some(p => p.endsWith('testDscProcess.dsc'))); - }); - - test('Libraries are populated', () => { - assert.ok(workspace.filesLibraries.length >= 2); - }); - - test('Modules are populated', () => { - assert.ok(workspace.filesModules.length >= 2); - }); - - test('getFilesList aggregates all lists', () => { - const all = workspace.getFilesList(); - assert.ok(all.length >= 4, - `Expected >=4 total files (dsc+libs+mods), got ${all.length}`); - }); - }); -}); - -// ═══════════════════════════════════════════════════════════════ -// proccessWorkspace (public API) tests -// ═══════════════════════════════════════════════════════════════ - -suite('EdkWorkspace.proccessWorkspace', () => { - test('proccessWorkspace runs without errors', async function () { - this.timeout(15_000); - ensureProcessingGlobals(); - const doc = await openDscDocument('testDscProcess.dsc'); - const workspace = new EdkWorkspace(doc); - const result = await workspace.proccessWorkspace(); - assert.ok(result === true, 'proccessWorkspace should return true'); - assert.strictEqual(workspace.platformName, 'TestProcess'); - }); - - test('proccessWorkspace populates defines and PCDs', async function () { - this.timeout(15_000); - ensureProcessingGlobals(); - const doc = await openDscDocument('testDscProcess.dsc'); - const workspace = new EdkWorkspace(doc); - await workspace.proccessWorkspace(); - assert.ok(workspace.getDefinitions().size > 0, 'Should have defines'); - assert.ok(workspace.getAllPcds().size > 0, 'Should have PCDs'); - }); -}); diff --git a/src/test/suite/extension.test.ts b/src/test/suite/extension.test.ts deleted file mode 100644 index 88f03d5..0000000 --- a/src/test/suite/extension.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -import * as vscode from 'vscode'; -// import * as myExtension from '../../extension'; - -suite('Extension Test Suite', () => { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showInformationMessage('Start all tests.'); - - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); - }); -}); diff --git a/src/test/suite/fdfParser.test.ts b/src/test/suite/fdfParser.test.ts deleted file mode 100644 index ef633bf..0000000 --- a/src/test/suite/fdfParser.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { FdfParser } from '../../edkParser/fdfParser'; -import { Edk2SymbolType } from '../../symbols/symbolsType'; -import { DebugLog } from '../../debugLog'; - -function ensureGlobals() { - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } -} - -async function parseFdfFile(filename: string): Promise { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test', filename); - const uri = vscode.Uri.file(filePath); - const document = await vscode.workspace.openTextDocument(uri); - const parser = new FdfParser(document); - await parser.parseFile(); - return parser; -} - -function symbolsOfType(parser: FdfParser, type: Edk2SymbolType) { - return parser.symbolsList.filter(s => s.type === type); -} - -suite('FDF Parser – Symbol Extraction', () => { - - let parser: FdfParser; - - suiteSetup(async function () { - this.timeout(10_000); - parser = await parseFdfFile('testFdfParsing.fdf'); - }); - - suite('Sections', () => { - test('Parses [FD.*] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.fdfSection); - const fd = sections.filter(s => /FD\./i.test(s.name)); - assert.ok(fd.length >= 1, `Expected >=1 FD section, got ${fd.length}`); - }); - - test('Parses [FV.*] sections', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.fdfSection); - const fv = sections.filter(s => /FV\./i.test(s.name)); - assert.ok(fv.length >= 2, `Expected >=2 FV sections, got ${fv.length}`); - }); - - test('Parses [Rule.*] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.fdfSection); - const rules = sections.filter(s => /Rule\./i.test(s.name)); - assert.ok(rules.length >= 1, `Expected >=1 Rule section, got ${rules.length}`); - }); - }); - - suite('INF References', () => { - test('Parses INF module references', () => { - const infs = symbolsOfType(parser, Edk2SymbolType.fdfInf); - assert.ok(infs.length >= 3, `Expected >=3 INF refs, got ${infs.length}`); - }); - }); - - suite('Defines', () => { - test('Parses DEFINE statements', () => { - const defs = symbolsOfType(parser, Edk2SymbolType.fdfDefinition); - assert.ok(defs.length >= 2, `Expected >=2 DEFINE statements, got ${defs.length}`); - }); - }); - - suite('Includes', () => { - test('Parses !include directive', () => { - const includes = symbolsOfType(parser, Edk2SymbolType.fdfInclude); - assert.ok(includes.length >= 1, 'Expected at least one !include'); - const inc = includes.find(s => /TestFdfInclude/i.test(s.name)); - assert.ok(inc, 'TestFdfInclude.fdf.inc should be found'); - }); - }); - - suite('Consistency', () => { - test('symbolsTree is not empty', () => { - assert.ok(parser.symbolsTree.length > 0, 'symbolsTree should not be empty'); - }); - - test('symbolsList equals recursive tree count', () => { - function countNodes(nodes: vscode.DocumentSymbol[]): number { - let c = 0; - for (const n of nodes) { c++; c += countNodes(n.children); } - return c; - } - assert.strictEqual(parser.symbolsList.length, countNodes(parser.symbolsTree)); - }); - - test('Comments are not parsed as symbols', () => { - for (const s of parser.symbolsList) { - assert.ok(!s.name.startsWith('#'), `Symbol should not start with #: "${s.name}"`); - } - }); - }); -}); diff --git a/src/test/suite/index.ts b/src/test/suite/index.ts deleted file mode 100644 index 7029e38..0000000 --- a/src/test/suite/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import * as path from 'path'; -import * as Mocha from 'mocha'; -import * as glob from 'glob'; - -export function run(): Promise { - // Create the mocha test - const mocha = new Mocha({ - ui: 'tdd', - color: true - }); - - const testsRoot = path.resolve(__dirname, '..'); - - return new Promise((c, e) => { - glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { - if (err) { - return e(err); - } - - // Add files to the test suite - files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); - - try { - // Run the mocha test - mocha.run(failures => { - if (failures > 0) { - e(new Error(`${failures} tests failed.`)); - } else { - c(); - } - }); - } catch (err) { - console.error(err); - e(err); - } - }); - }); -} diff --git a/src/test/suite/infParser.test.ts b/src/test/suite/infParser.test.ts deleted file mode 100644 index 095c038..0000000 --- a/src/test/suite/infParser.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { InfParser } from '../../edkParser/infParser'; -import { Edk2SymbolType } from '../../symbols/symbolsType'; -import { DebugLog } from '../../debugLog'; - -function ensureGlobals() { - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } -} - -async function parseInfFile(filename: string): Promise { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test', filename); - const uri = vscode.Uri.file(filePath); - const document = await vscode.workspace.openTextDocument(uri); - const parser = new InfParser(document); - await parser.parseFile(); - return parser; -} - -function symbolsOfType(parser: InfParser, type: Edk2SymbolType) { - return parser.symbolsList.filter(s => s.type === type); -} - -suite('INF Parser – Symbol Extraction', () => { - - let parser: InfParser; - - suiteSetup(async function () { - this.timeout(10_000); - parser = await parseInfFile('testInfParsing.inf'); - }); - - suite('Sections', () => { - test('Parses [Defines] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSection); - const defines = sections.filter(s => /defines/i.test(s.name)); - assert.ok(defines.length >= 1, 'Expected at least one [Defines] section'); - }); - - test('Parses [Sources] section(s)', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionSource); - assert.ok(sections.length >= 1, `Expected >=1 Sources section, got ${sections.length}`); - }); - - test('Parses [Packages] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionPackages); - assert.ok(sections.length >= 1, 'Expected at least one [Packages] section'); - }); - - test('Parses [LibraryClasses] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionLibraries); - assert.ok(sections.length >= 1, 'Expected at least one [LibraryClasses] section'); - }); - - test('Parses [Protocols] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionProtocols); - assert.ok(sections.length >= 1, 'Expected at least one [Protocols] section'); - }); - - test('Parses [Ppis] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionPpis); - assert.ok(sections.length >= 1, 'Expected at least one [Ppis] section'); - }); - - test('Parses [Guids] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionGuids); - assert.ok(sections.length >= 1, 'Expected at least one [Guids] section'); - }); - - test('Parses [Pcd] / [FixedPcd] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionPcds); - assert.ok(sections.length >= 1, 'Expected at least one PCD section'); - }); - - test('Parses [Depex] section', () => { - const sections = symbolsOfType(parser, Edk2SymbolType.infSectionDepex); - assert.ok(sections.length >= 1, 'Expected at least one [Depex] section'); - }); - }); - - suite('Defines', () => { - test('Parses INF defines (MODULE_TYPE, BASE_NAME, etc.)', () => { - const defines = symbolsOfType(parser, Edk2SymbolType.infDefine); - assert.ok(defines.length >= 7, `Expected >=7 defines, got ${defines.length}`); - }); - - test('Parses ENTRY_POINT define', () => { - const defines = symbolsOfType(parser, Edk2SymbolType.infDefine); - const ep = defines.find(s => /ENTRY_POINT/i.test(s.name)); - assert.ok(ep, 'ENTRY_POINT should be parsed'); - }); - - test('Parses CONSTRUCTOR define', () => { - const defines = symbolsOfType(parser, Edk2SymbolType.infDefine); - const ctor = defines.find(s => /CONSTRUCTOR/i.test(s.name)); - assert.ok(ctor, 'CONSTRUCTOR should be parsed'); - }); - - test('Parses DESTRUCTOR define', () => { - const defines = symbolsOfType(parser, Edk2SymbolType.infDefine); - const dtor = defines.find(s => /DESTRUCTOR/i.test(s.name)); - assert.ok(dtor, 'DESTRUCTOR should be parsed'); - }); - }); - - suite('Sources', () => { - test('Parses source file entries', () => { - const sources = symbolsOfType(parser, Edk2SymbolType.infSource); - assert.ok(sources.length >= 3, `Expected >=3 source entries, got ${sources.length}`); - }); - }); - - suite('Packages', () => { - test('Parses package references', () => { - const packages = symbolsOfType(parser, Edk2SymbolType.infPackage); - assert.ok(packages.length >= 2, `Expected >=2 packages, got ${packages.length}`); - }); - }); - - suite('Libraries', () => { - test('Parses library class references', () => { - const libs = symbolsOfType(parser, Edk2SymbolType.infLibrary); - assert.ok(libs.length >= 3, `Expected >=3 library references, got ${libs.length}`); - }); - }); - - suite('Protocols', () => { - test('Parses protocol entries', () => { - const protocols = symbolsOfType(parser, Edk2SymbolType.infProtocol); - assert.ok(protocols.length >= 2, `Expected >=2 protocols, got ${protocols.length}`); - }); - }); - - suite('PPIs', () => { - test('Parses PPI entries', () => { - const ppis = symbolsOfType(parser, Edk2SymbolType.infPpi); - assert.ok(ppis.length >= 1, `Expected >=1 PPI, got ${ppis.length}`); - }); - }); - - suite('GUIDs', () => { - test('Parses GUID entries', () => { - const guids = symbolsOfType(parser, Edk2SymbolType.infGuid); - assert.ok(guids.length >= 2, `Expected >=2 GUIDs, got ${guids.length}`); - }); - }); - - suite('PCDs', () => { - test('Parses PCD entries', () => { - const pcds = symbolsOfType(parser, Edk2SymbolType.infPcd); - assert.ok(pcds.length >= 1, `Expected >=1 PCD, got ${pcds.length}`); - }); - }); - - suite('Depex', () => { - test('Parses dependency expression entries', () => { - const depex = symbolsOfType(parser, Edk2SymbolType.infDepex); - assert.ok(depex.length >= 1, `Expected >=1 depex entry, got ${depex.length}`); - }); - }); - - suite('Consistency', () => { - test('symbolsTree is not empty', () => { - assert.ok(parser.symbolsTree.length > 0, 'symbolsTree should not be empty'); - }); - - test('symbolsList equals recursive tree count', () => { - function countNodes(nodes: vscode.DocumentSymbol[]): number { - let c = 0; - for (const n of nodes) { c++; c += countNodes(n.children); } - return c; - } - assert.strictEqual(parser.symbolsList.length, countNodes(parser.symbolsTree)); - }); - - test('Comments are not parsed as symbols', () => { - for (const s of parser.symbolsList) { - assert.ok(!s.name.startsWith('#'), `Symbol should not start with #: "${s.name}"`); - } - }); - }); -}); diff --git a/src/test/suite/vfrParser.test.ts b/src/test/suite/vfrParser.test.ts deleted file mode 100644 index 714f7e1..0000000 --- a/src/test/suite/vfrParser.test.ts +++ /dev/null @@ -1,116 +0,0 @@ -import * as assert from 'assert'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { VfrParser } from '../../edkParser/vfrParser'; -import { Edk2SymbolType } from '../../symbols/symbolsType'; -import { DebugLog } from '../../debugLog'; - -function ensureGlobals() { - const ext = require('../../extension'); - if (!ext.gDebugLog) { - ext.gDebugLog = new DebugLog(); - } -} - -async function parseVfrFile(filename: string): Promise { - ensureGlobals(); - const filePath = path.resolve(__dirname, '../../../test', filename); - const uri = vscode.Uri.file(filePath); - const document = await vscode.workspace.openTextDocument(uri); - const parser = new VfrParser(document); - await parser.parseFile(); - return parser; -} - -function symbolsOfType(parser: VfrParser, type: Edk2SymbolType) { - return parser.symbolsList.filter(s => s.type === type); -} - -suite('VFR Parser – Symbol Extraction', () => { - - let parser: VfrParser; - - suiteSetup(async function () { - this.timeout(10_000); - parser = await parseVfrFile('testVfrParsing.vfr'); - }); - - suite('Formset', () => { - test('Parses formset', () => { - const formsets = symbolsOfType(parser, Edk2SymbolType.vfrFormset); - assert.ok(formsets.length >= 1, 'Expected at least one formset'); - }); - - test('Parses form blocks', () => { - const forms = symbolsOfType(parser, Edk2SymbolType.vfrForm); - assert.ok(forms.length >= 0, `Unexpected negative form count: ${forms.length}`); - }); - }); - - suite('Controls', () => { - test('Parses oneof controls', () => { - const oneofs = symbolsOfType(parser, Edk2SymbolType.vfrOneof); - assert.ok(oneofs.length >= 2, `Expected >=2 oneofs, got ${oneofs.length}`); - }); - - test('Parses checkbox controls', () => { - const checkboxes = symbolsOfType(parser, Edk2SymbolType.vfrCheckbox); - assert.ok(checkboxes.length >= 1, `Expected >=1 checkbox, got ${checkboxes.length}`); - }); - - test('Parses numeric controls', () => { - const numerics = symbolsOfType(parser, Edk2SymbolType.vfrNumeric); - assert.ok(numerics.length >= 1, `Expected >=1 numeric, got ${numerics.length}`); - }); - - test('Parses string controls', () => { - const strings = symbolsOfType(parser, Edk2SymbolType.vfrString); - assert.ok(strings.length >= 1, `Expected >=1 string control, got ${strings.length}`); - }); - - test('Parses password controls', () => { - const passwords = symbolsOfType(parser, Edk2SymbolType.vfrPassword); - assert.ok(passwords.length >= 1, `Expected >=1 password control, got ${passwords.length}`); - }); - - test('Parses goto references', () => { - const gotos = symbolsOfType(parser, Edk2SymbolType.vfrGoto); - assert.ok(gotos.length >= 2, `Expected >=2 goto refs, got ${gotos.length}`); - }); - - test('Parses prompt entries inside controls', () => { - const prompts = symbolsOfType(parser, Edk2SymbolType.vfrString); - assert.ok(prompts.length >= 2, `Expected >=2 prompt/string entries, got ${prompts.length}`); - }); - }); - - suite('Tree Structure', () => { - test('symbolsTree is not empty', () => { - assert.ok(parser.symbolsTree.length > 0); - }); - - test('Formset or form has children', () => { - const formsets = symbolsOfType(parser, Edk2SymbolType.vfrFormset); - const forms = symbolsOfType(parser, Edk2SymbolType.vfrForm); - const withChildren = [...formsets, ...forms].filter(s => s.children.length > 0); - assert.ok(withChildren.length > 0, 'At least one formset or form should have children'); - }); - }); - - suite('Consistency', () => { - test('symbolsList equals recursive tree count', () => { - function countNodes(nodes: vscode.DocumentSymbol[]): number { - let c = 0; - for (const n of nodes) { c++; c += countNodes(n.children); } - return c; - } - assert.strictEqual(parser.symbolsList.length, countNodes(parser.symbolsTree)); - }); - - test('Comments are not parsed as symbols', () => { - for (const s of parser.symbolsList) { - assert.ok(!s.name.startsWith('//'), `Symbol should not start with //: "${s.name}"`); - } - }); - }); -}); diff --git a/src/treeElements/DefinesTreeItem.ts b/src/treeElements/DefinesTreeItem.ts deleted file mode 100644 index 73283d5..0000000 --- a/src/treeElements/DefinesTreeItem.ts +++ /dev/null @@ -1,70 +0,0 @@ -import * as vscode from 'vscode'; -import { gEdkWorkspaces } from '../extension'; -import { TreeItem } from './TreeItem'; - -export class DefinesRootItem extends TreeItem { - constructor( label: string) { - super(label, vscode.TreeItemCollapsibleState.Collapsed); - } - - // Override to populate children dynamically - async expand() { - this.children = []; // Clear current children - - if (this.label === "DEFINES") { - this.populateDefines(); - } else if (this.label === "PCDs") { - this.populatePcds(); - } - } - - private populateDefines() { - if (!gEdkWorkspaces || !gEdkWorkspaces.workspaces) { return; } - - for (const wp of gEdkWorkspaces.workspaces) { - let defs = wp.getDefinitions(); - for (const [key, value] of defs.entries()) { - const label = `${key}`; - const item = new TreeItem(label, vscode.TreeItemCollapsibleState.None); - item.description = value.value; - if (value.location) { - item.command = { - command: 'vscode.open', - title: 'Open', - arguments: [value.location.uri, { selection: value.location.range }] - }; - item.tooltip = label; - } - this.addChildren(item); - } - } - } - - private populatePcds() { - if (!gEdkWorkspaces || !gEdkWorkspaces.workspaces) { return; } - - for (const wp of gEdkWorkspaces.workspaces) { - let pcds = wp.getAllPcds(); - for (const [namespace, pcdMap] of pcds) { - for (const [name, pcd] of pcdMap) { - const label = `${namespace}.${name} = ${pcd.value}`; - const item = new TreeItem(label, vscode.TreeItemCollapsibleState.None); - item.command = { - command: 'vscode.open', - title: 'Open', - arguments: [pcd.position.uri, { selection: pcd.position.range }] - }; - item.tooltip = label; - this.addChildren(item); - } - } - } - } - - // Needed because TreeItem implementation uses it - addChildren(node: TreeItem) { - node.parent = this; - // this.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; // Don't auto expand when adding children internally - this.children.push(node); - } -} diff --git a/src/treeElements/EdkObject.ts b/src/treeElements/EdkObject.ts deleted file mode 100644 index 994e1ae..0000000 --- a/src/treeElements/EdkObject.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { EdkWorkspace } from "../index/edkWorkspace"; -import { EdkSymbol } from "../symbols/edkSymbols"; -import { TreeItem } from "./TreeItem"; -import * as vscode from 'vscode'; - -export class EdkNode extends TreeItem { - uri:vscode.Uri; - loaded = false; - workspace:EdkWorkspace; - edkObject:EdkSymbol|undefined; - contextModuleUri:vscode.Uri|undefined = undefined; - - constructor(uri:vscode.Uri, position:vscode.Position, wp:EdkWorkspace, edkObject:EdkSymbol|undefined){ - super(uri, vscode.TreeItemCollapsibleState.Collapsed); - this.edkObject = edkObject; - this.workspace = wp; - this.uri = uri; - - this.command = { - "command": "editor.action.peekLocations", - "title":"Open file", - "arguments": [this.uri, position, []] - }; - - } - - async expand(){ - - } - - - - } - \ No newline at end of file diff --git a/src/treeElements/Library.ts b/src/treeElements/Library.ts deleted file mode 100644 index 60d557a..0000000 --- a/src/treeElements/Library.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { InfParser } from "../edkParser/infParser"; -import { getParser } from "../edkParser/parserFactory"; -import { gConfigAgent, gDebugLog, gPathFind } from "../extension"; -import { EdkWorkspace } from "../index/edkWorkspace"; -import { EdkSymbol } from "../symbols/edkSymbols"; -import { EdkSymbolInfLibrary, EdkSymbolInfSource } from "../symbols/infSymbols"; -import { Edk2SymbolType } from "../symbols/symbolsType"; -import { EdkNode } from "./EdkObject"; -import * as vscode from 'vscode'; -import { EdkSourceNode } from "./Source"; -import { ConfigAgent } from "../configuration"; - - - - -export class EdkInfNode extends EdkNode{ - contextUri:vscode.Uri; - librarySet:Set|undefined; - constructor(uri:vscode.Uri, contextUri:vscode.Uri, position:vscode.Position, wp:EdkWorkspace, edkObject:EdkSymbol, librarySet?:Set|undefined){ - super(uri, position, wp, edkObject); - this.contextUri = contextUri; - this.description = `${uri.fsPath}`; - this.iconPath = new vscode.ThemeIcon("extensions"); - this.command = { - "command": "vscode.open", - "title":"Open file", - "arguments": [this.uri] - }; - this.librarySet = librarySet; - - - void getParser(this.uri).then(async (parser)=>{ - if(parser){ - let defines = parser.getSymbolsType(Edk2SymbolType.infDefine); - let libraryClass = ""; - for (const define of defines) { - if((await define.getKey()).toLowerCase() === "library_class"){ - libraryClass = (await define.getValue() || "").split("|")[0]; - this.label = libraryClass; - break; - } - } - } - }); - - - - } - - - async expand(){ - await this.expandWithLoading(async ()=>{ - let parser = await getParser(this.uri); - - if(parser === undefined){ - gDebugLog.error("Parser not found for file: " + this.uri.fsPath); - return; - } - let contextProperties = await this.workspace.getDscProperties(this.contextUri); - - let libraries = parser.getSymbolsType(Edk2SymbolType.infLibrary, contextProperties) as EdkSymbolInfLibrary[]; - - // Load libraries - for await (const library of libraries) { - let libDefinitions = await this.workspace.getLibDeclarationModule(this.contextUri, library.name); - for (const libDefinition of libDefinitions) { - let filePaths = await gPathFind.findPath(libDefinition.path); - for (const path of filePaths) { - let childLibNode = new EdkInfNodeLibrary(path.uri, this.contextUri, new vscode.Position(0,0), this.workspace, library, this.librarySet); - this.addChildren(childLibNode); - - // Check circular dependencies - for (const parent of childLibNode.iterateParents()) { - if(parent instanceof EdkInfNode){ - if(parent.uri.fsPath === childLibNode.uri.fsPath){ - childLibNode.setCircularDependency(); - break; - } - } - } - } - } - } - - let sources = parser.getSymbolsType(Edk2SymbolType.infSource, contextProperties) as EdkSymbolInfSource[]; - for (const source of sources) { - let filePath = await source.getValue(); - - if(!filePath.toLowerCase().endsWith(".c")){continue;} // Only C files - - let pos = new vscode.Position(0,0); - let fileUri = vscode.Uri.file(filePath); - let childSourceNode = new EdkSourceNode(fileUri, this.contextUri, pos, this.workspace, source, this.librarySet); - this.addChildren(childSourceNode); - - } - }); - - - - - - - - } - - setDuplicatedLibrary(){ - if(!gConfigAgent.getExpandCircularOrDuplicateLibraries()){ - this.collapsibleState = vscode.TreeItemCollapsibleState.None; - } - this.description = `(Duplicated library)`; - this.tooltip = "Duplicated library"; - } - - setCircularDependency(){ - if(!gConfigAgent.getExpandCircularOrDuplicateLibraries()){ - this.collapsibleState = vscode.TreeItemCollapsibleState.None; - } - this.description = `(Circular dependency)`; - this.iconPath = new vscode.ThemeIcon("extensions-refresh"); - this.tooltip = "Circular library dependency"; - } - -} - -export class EdkInfNodeLibrary extends EdkInfNode{ - constructor(uri:vscode.Uri, contextUri:vscode.Uri, position:vscode.Position, wp:EdkWorkspace, edkObject:EdkSymbol, librarySet?:Set|undefined){ - super(uri, contextUri, position, wp, edkObject, librarySet); - this.iconPath = new vscode.ThemeIcon("library"); - if(librarySet){ - if(librarySet.has(uri.fsPath)){ - this.setDuplicatedLibrary(); - }else{ - librarySet.add(uri.fsPath); - gDebugLog.trace(`${uri.fsPath}`); - } - } - } -} \ No newline at end of file diff --git a/src/treeElements/Source.ts b/src/treeElements/Source.ts deleted file mode 100644 index 7e27b9c..0000000 --- a/src/treeElements/Source.ts +++ /dev/null @@ -1,129 +0,0 @@ -import path = require("path"); -import { CompileCommandsEntry } from "../compileCommands"; -import { InfParser } from "../edkParser/infParser"; -import { getParser } from "../edkParser/parserFactory"; -import { gCompileCommands, gDebugLog, gMapFileManager, gPathFind } from "../extension"; -import { EdkWorkspace } from "../index/edkWorkspace"; -import { EdkSymbol } from "../symbols/edkSymbols"; -import { EdkSymbolInfLibrary, EdkSymbolInfSource } from "../symbols/infSymbols"; -import { Edk2SymbolType } from "../symbols/symbolsType"; -import { getAllSymbols, openTextDocument } from "../utils"; -import { EdkNode } from "./EdkObject"; -import * as vscode from 'vscode'; -import { DiagnosticManager, EdkDiagnosticCodes } from "../diagnostics"; -import { EdkSymbolNode } from "./Symbol"; - - - -export class EdkSourceNode extends EdkNode{ - contextUri:vscode.Uri; - librarySet:Set|undefined; - constructor(uri:vscode.Uri, contextUri:vscode.Uri, position:vscode.Position, wp:EdkWorkspace, edkObject:EdkSymbol|undefined, librarySet?:Set|undefined){ - super(uri, position, wp, edkObject); - this.contextUri = contextUri; - this.iconPath = new vscode.ThemeIcon("file"); - this.command = { - "command": "vscode.open", - "title":"Open file", - "arguments": [this.uri] - }; - } - - - async expand(){ - await this.expandWithLoading(async ()=>{ - // Find includes - const compileCommand = gCompileCommands.getCompileCommandForFile(this.uri.fsPath); - if(compileCommand){ - const includeHeaders = await this.findIncludes(); - for await (const includeHeader of includeHeaders) { - this.addChildren(includeHeader); - updateCompileCommandsForHeaderFile(includeHeader.uri, compileCommand); - } - } - - // Symbols - // TODO: experimental function - if(false){ - const sourceSymbols:vscode.DocumentSymbol[] = await getAllSymbols(this.uri); - for (const symbol of sourceSymbols) { - const symbolNode = new EdkSymbolNode(this.uri, symbol, this.workspace); - if(symbol.kind === vscode.SymbolKind.Function){ - if(!gMapFileManager.isSymbolUsed(symbol.name)){ - DiagnosticManager.warning(this.uri,symbol.range,EdkDiagnosticCodes.unusedSymbol, `Unused function: ${symbol.name}`, [vscode.DiagnosticTag.Unnecessary]); - symbolNode.tooltip = "Unused function"; - symbolNode.description = `Unused ${symbolNode.description}`; - symbolNode.iconPath = new vscode.ThemeIcon("warning"); - } - } - this.addChildren(symbolNode); - } - } - - }); - } - - async findIncludes(){ - let sourceDocument = await openTextDocument(this.uri); - let sourceText = sourceDocument.getText(); - let lineNo = 0; - let includeNodes:EdkSourceNode[] = []; - let compiledIncludePaths: string[] = []; - const compileCommand = gCompileCommands.getCompileCommandForFile(this.uri.fsPath); - if(compileCommand){ - compiledIncludePaths = compileCommand.getIncludePaths(); - } - - for (const line of sourceText.split('\n')) { - let match = /#include\s+(["<])([^">]+)[">]/.exec(line); - if(match){ - let isRelative = false; - - if(match[1] === '"'){ - isRelative = true; - } - let includePath = match[2]; - - let includeUri:vscode.Uri|undefined = undefined; - - if(isRelative){ - // Relative includes - const locations = await gPathFind.findRelativePath(includePath, path.dirname(this.uri.fsPath)); - if(locations){ - includeUri = locations.uri; - } - }else{ - // System includes - for (const compiledIncludePath of compiledIncludePaths) { - const location = await gPathFind.findRelativePath(includePath, compiledIncludePath); - if(location){ - includeUri = location.uri; - break; - } - } - } - - let includeNode = new EdkSourceNode(includeUri||this.uri, this.contextUri, new vscode.Position(lineNo, 0), this.workspace, undefined, this.librarySet); - if(includeUri === undefined){ - includeNode.label = includePath; - includeNode.tooltip = "Missing include"; - includeNode.description = "Missing include"; - includeNode.collapsibleState = vscode.TreeItemCollapsibleState.None; - DiagnosticManager.error(this.uri,new vscode.Range(new vscode.Position(lineNo, 0), new vscode.Position(lineNo, line.length)),EdkDiagnosticCodes.includePathNotFound, `Missing include: ${includePath}`); - } - includeNodes.push(includeNode); - } - lineNo++; - } - return includeNodes; - - } - - -} - -function updateCompileCommandsForHeaderFile(headerItem:vscode.Uri, compileCommand:CompileCommandsEntry){ - let tempCompileCommand = new CompileCommandsEntry(compileCommand.command, "", headerItem.fsPath); - gCompileCommands.addCompileCommandForFile(tempCompileCommand); -} - diff --git a/src/treeElements/Symbol.ts b/src/treeElements/Symbol.ts deleted file mode 100644 index 012c307..0000000 --- a/src/treeElements/Symbol.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { InfParser } from "../edkParser/infParser"; -import { getParser } from "../edkParser/parserFactory"; -import { gDebugLog, gPathFind } from "../extension"; -import { EdkWorkspace } from "../index/edkWorkspace"; -import { EdkSymbol } from "../symbols/edkSymbols"; -import { EdkSymbolInfLibrary, EdkSymbolInfSource } from "../symbols/infSymbols"; -import { Edk2SymbolType } from "../symbols/symbolsType"; -import { EdkNode } from "./EdkObject"; -import * as vscode from 'vscode'; -import { EdkSourceNode } from "./Source"; -import { TreeItem } from "./TreeItem"; -import { documentGetText, documentGetTextSync, getSymbolAtLocation, openTextDocumentInRange } from "../utils"; - - -var baseTypeSet = new Set([ -"UINTN", -"INTN", -"UINT64", -"INT64", -"UINT32", -"INT32", -"UINT16", -"CHAR16", -"INT16", -"BOOLEAN", -"UINT8", -"CHAR8", -"INT8" -]); - - -export class EdkSymbolNode extends EdkNode{ - uri:vscode.Uri; - range:vscode.Range; - name:string; - baseType:boolean = false; - constructor(uri:vscode.Uri, symbol:vscode.DocumentSymbol, wp:EdkWorkspace){ - super(uri, symbol.range.start, wp, undefined); - - this.label = symbol.name; - this.name = symbol.name; - this.description = symbol.detail.length?symbol.detail:vscode.SymbolKind[symbol.kind]; - this.iconPath = EdkSymbol.iconForKind(symbol.kind); - this.collapsibleState = vscode.TreeItemCollapsibleState.None; - this.range = symbol.range; - this.uri = uri; - - // Fix typedef label rendering - if(symbol.kind === vscode.SymbolKind.Interface){ - let text = documentGetTextSync(this.uri, symbol.range); - let clearText = text.replace(symbol.detail,"").replace(/\s+/g, ' ').replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '').replaceAll("\n"," ").replaceAll("\r","").trim(); - if(!clearText.match(/^(struct|enum|union)/)){ - this.label = clearText; - } - } - - - // Avoid expand basetypes - let baseTypeDef = false; - if(this.description === "typedef"){ - baseTypeDef = baseTypeSet.has(this.label.split(" ")[0].trim()); - } - - this.baseType = baseTypeDef || baseTypeSet.has(this.description); - - if(!this.baseType){ // Skip base types children - for (const child of symbol.children) { - let newChild = new EdkSymbolNode(uri,child, this.workspace); - this.addChildren(newChild); - this.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; - // Get the type parsing the definition - void documentGetText(this.uri, child.range).then((text) => { - const childType = text.trim().split(" ")[0]; - newChild.description = childType; - if(baseTypeSet.has(childType)){ - newChild.collapsibleState = vscode.TreeItemCollapsibleState.None; - } - }); - } - } - - - if(symbol.kind === vscode.SymbolKind.Field){ - this.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; - } - - - this.command = { - "command": "editor.action.peekLocations", - "title":"Open file", - "arguments": [this.uri, symbol.range.start, []] - }; - - } - - async expand() { - await this.expandWithLoading(async ()=>{ - await openTextDocumentInRange(this.uri, this.range); - if(this.children.length > 0){return;} - - // Find definition for field - const locations = await vscode.commands.executeCommand('vscode.executeTypeDefinitionProvider', this.uri, this.range.start); - if(locations.length > 0){ - let symbol = await getSymbolAtLocation(locations[0].uri, locations[0]); - if(symbol){ - - if(symbol.kind === vscode.SymbolKind.Interface){ - const locationsType = await vscode.commands.executeCommand('vscode.executeTypeDefinitionProvider',locations[0].uri , locations[0].range.start); - if(locationsType.length > 0){ - symbol = await getSymbolAtLocation(locationsType[0].uri, locationsType[0]); - if(!symbol){return;} - } - } - - let symbolNode = new EdkSymbolNode(locations[0].uri, symbol, this.workspace); - - - if(symbolNode.name.includes("unnamed") && symbolNode.children.length> 0 && !symbolNode.baseType){ - for (const child of symbolNode.children) { - this.addChildren(child); - } - }else{ - this.addChildren(symbolNode); - } - symbolNode.collapsibleState = vscode.TreeItemCollapsibleState.Collapsed; - - }else{ - this.collapsibleState = vscode.TreeItemCollapsibleState.None; - } - } - }); - } - } \ No newline at end of file diff --git a/src/treeElements/TreeItem.ts b/src/treeElements/TreeItem.ts deleted file mode 100644 index f1d3cc9..0000000 --- a/src/treeElements/TreeItem.ts +++ /dev/null @@ -1,82 +0,0 @@ -import * as vscode from 'vscode'; - -export class TreeItem extends vscode.TreeItem { - children: TreeItem[] = []; - parent: TreeItem | undefined; - visible:boolean = true; - - private tempIcon = this.iconPath; - - getParent() { - return this.parent; - } - - addChildren(node: TreeItem) { - node.parent = this; - this.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; - this.children.push(node); - } - - *iterateChildren(): IterableIterator { - for (const child of this.children) { - yield child; - yield* child.iterateChildren(); - } - } - - *iterateParents(): IterableIterator { - let current: TreeItem | undefined = this.parent; - while (current) { - yield current; - current = current.parent; - } - } - - toString(){ - let result = ""; - if(typeof this.label === 'string'){ - result = `**${this.label}**`; - } - if(typeof this.label === 'object' && 'label' in this.label){ - result = `**${this.label.label}**`; - } - - result += this.description ? ` - *${this.description}*` : ''; - return result; - } - - async expand(){} - - setLoading(){ - this.tempIcon = this.iconPath; - this.iconPath = new vscode.ThemeIcon("loading~spin"); - } - - clearLoading(){ - this.iconPath = this.tempIcon; - } - - needsExpandProcess(){ - if(this.collapsibleState === vscode.TreeItemCollapsibleState.None){ - return false; - } - - if(this.children.length > 0){ - this.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; - return false; - } - - return true; - } - - async expandWithLoading(expandFunction:Function){ - if(this.needsExpandProcess()){ - this.setLoading(); - await expandFunction(); - this.clearLoading(); - if(this.children.length === 0){ - this.collapsibleState = vscode.TreeItemCollapsibleState.None; - } - } - } - } \ No newline at end of file diff --git a/src/ui/messages.ts b/src/ui/messages.ts deleted file mode 100644 index 88b69ad..0000000 --- a/src/ui/messages.ts +++ /dev/null @@ -1,79 +0,0 @@ -import * as vscode from 'vscode'; -import { rescanIndex } from '../contextState/cmds'; -import { gConfigAgent, gCscope } from '../extension'; -import { delay } from '../utils'; - - -export function askReloadFiles(){ - void vscode.window.showInformationMessage("Configuration changed. Need to rescan index", "Rescan now").then(async selection => { - if (selection === "Rescan now"){ - await rescanIndex(); - - } - }); -} - - -export function infoMissingCompileInfo(){ - void vscode.window.showInformationMessage("EDK2 Compile Information folder is missing.", "How to enable?").then(async selection => { - if (selection === "How to enable?"){ - void vscode.env.openExternal(vscode.Uri.parse("https://intel.github.io/Edk2Code/advance_features/#how-to-enable-compile-information")); - } - }); -} - - - -export function infoMissingCppExtension() { - if (gConfigAgent.isWarningCppExtension()) { - void vscode.window.showInformationMessage( - "The MS C/C++ or Clangd extension is not installed. Please install one of those to use full EDK2Code features.", - "Install Extension", - "Don't show this message again", - "Close" - ).then(async selection => { - if (selection === "Install Extension") { - const extensionChoice = await vscode.window.showQuickPick( - ["C/C++ for Visual Studio Code", "Clangd"], - { placeHolder: "Select the extension to install" } - ); - - if (extensionChoice === "C/C++ for Visual Studio Code") { - void vscode.env.openExternal(vscode.Uri.parse('vscode:extension/ms-vscode.cpptools')); - } else if (extensionChoice === "Clangd") { - void vscode.env.openExternal(vscode.Uri.parse('vscode:extension/llvm-vs-code-extensions.vscode-clangd')); - } - } else if (selection === "Don't show this message again") { - await gConfigAgent.setWarningCppExtension(false); - } - }); - } -} - - -export async function isFixWorkspacePath(buildPath:string, workspacePath:string):Promise{ - return new Promise(async (resolve, reject) => { - return vscode.window.showInformationMessage(`The Active platform in the build directory "${buildPath}" is different than Vscode Workspace path folder "${workspacePath}". Do you want EDK2Code to attempt to fix it? **Build directory wont be modified by this**`, "Yes", "No").then(async selection => { - if (selection === "Yes"){ - resolve(true); - }else{ - resolve(false); - } - }); - }); - -} - - -export async function updateCompilesCommandCpp():Promise{ - return new Promise(async (resolve, reject) => { - return vscode.window.showInformationMessage("c_cpp_properties.json/settings.json points to wrong compile_commands.json", "Fix").then(async selection => { - if (selection === "Fix"){ - resolve(true); - }else{ - resolve(false); - } - }); - }); - -} \ No newline at end of file diff --git a/src/usedFileTracker.ts b/src/usedFileTracker.ts deleted file mode 100644 index e3b6f3f..0000000 --- a/src/usedFileTracker.ts +++ /dev/null @@ -1,86 +0,0 @@ -import * as vscode from 'vscode'; -import * as edkStatusBar from './statusBar'; -import path = require('path'); -import { gCscope, gEdkWorkspaces } from './extension'; - - - - -export class FileUseWarning { - constructor() { - vscode.window.onDidChangeActiveTextEditor(async (editor)=> { - if(editor){ - await this.fileOpened(editor); - } - }); - } - - - - - async fileOpened(editor: vscode.TextEditor) { - - // Get opened file - - let document = editor.document; - - let langId = document.languageId; - if(langId===undefined){return;} - if(!["c","cpp","edk2_dsc","edk2_inf","edk2_dec","asl","edk2_vfr","edk2_fdf", "edk2_uni"].includes(langId)){ - edkStatusBar.setColor('statusBarItem.activeBackground'); - edkStatusBar.setHelpUrl("https://intel.github.io/Edk2Code/"); - edkStatusBar.setText(`No EDK file`); - return; - } - - - - // Set status bar with no contex of file - edkStatusBar.setColor('statusBarItem.activeBackground'); - edkStatusBar.setText(``); - - // - // Notify user if file is in use - // - if(gEdkWorkspaces.isConfigured()){ - let wps = await gEdkWorkspaces.getWorkspace(editor.document.uri); - let wpFound = []; - for (const wp of wps) { - if(await wp.isFileInUse(editor.document.uri)){ - wpFound.push(wp.platformName); - - } - } - - if(wpFound.length){ - edkStatusBar.setHelpUrl("https://intel.github.io/Edk2Code/"); - edkStatusBar.setColor('statusBarItem.activeBackground'); - edkStatusBar.setText(`${wpFound.join("|")}`); - edkStatusBar.setToolTip(""); - return; - } - - // If file is an H file, then check in cscope.files - if(gCscope.includesFile(editor.document.uri)){ - edkStatusBar.setHelpUrl("https://intel.github.io/Edk2Code/"); - edkStatusBar.setColor('statusBarItem.activeBackground'); - edkStatusBar.setText(`(Included Path) ${path.basename(document.fileName)}`); - edkStatusBar.setToolTip(""); - return; - } - edkStatusBar.setColor('statusBarItem.warningBackground'); - edkStatusBar.setHelpUrl("https://intel.github.io/Edk2Code/getting_started/#status-bar"); - edkStatusBar.setText(`$(warning) ${path.basename(document.fileName)}`); - edkStatusBar.setToolTip("This file is not used by any loaded workspace"); - return; - }else{ - edkStatusBar.setHelpUrl("https://intel.github.io/Edk2Code/advance_features/#indexing-source-code"); - edkStatusBar.setColor('statusBarItem.activeBackground'); - edkStatusBar.setText(`Workspace not found`); - edkStatusBar.setToolTip("No workspace is configured"); - } - - } -} - - diff --git a/src/utilities/getNonce.ts b/src/utilities/getNonce.ts deleted file mode 100644 index f3631e5..0000000 --- a/src/utilities/getNonce.ts +++ /dev/null @@ -1,10 +0,0 @@ -// file: src/utilities/getNonce.ts - -export function getNonce() { - let text = ""; - const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (let i = 0; i < 32; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; - } \ No newline at end of file diff --git a/src/utilities/getUri.ts b/src/utilities/getUri.ts deleted file mode 100644 index 1c70713..0000000 --- a/src/utilities/getUri.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Uri, Webview } from "vscode"; - -export function getUri(webview: Webview, extensionUri: Uri, pathList: string[]) { - return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList)); -} \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index dfd71a5..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,559 +0,0 @@ -import path = require("path"); -import * as cp from 'child_process'; -import * as fs from 'fs'; -import * as vscode from 'vscode'; -import { cwd } from "process"; -import { gCompileCommands, gDebugLog, gEdkWorkspaces, gExtensionContext, gWorkspacePath } from "./extension"; -import { rejects } from "assert"; -import { REGEX_PCD } from "./edkParser/commonParser"; - - -var normalizeCache = new Map(); - -export function toPosix(textPath: string) { - return textPath.split(path.sep).join(path.posix.sep); -} - -export async function execWindow(cmd: string, cwdIn: string, winText: string) { - return vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: winText, - cancellable: true - }, async (progress, reject) => { - return new Promise((resolve, token) => { - var result = cp.execSync(cmd, { cwd: cwdIn }); - resolve(result.toString()); - }); - }); -} - -export async function exec(cmd: string, cwdIn: string) { - return new Promise((resolve, token) => { - cp.exec(cmd, { cwd: cwdIn, maxBuffer: undefined }, (err, out) => { - if (err) { - gDebugLog.error(err.stack!); - return resolve(""); - } - return resolve(out); - }); - // var result = cp.execSync(cmd, { cwd: cwdIn }); - // resolve(result.toString()); - }); - -} - -export async function documentGetText(uri:vscode.Uri,range:vscode.Range){ - let document = await openTextDocument(uri); - return document.getText(range); -} - -export function documentGetTextSync(uri: vscode.Uri, range: vscode.Range): string { - const documentPath = uri.fsPath; - const documentContent = fs.readFileSync(documentPath, 'utf-8'); - - const start = documentContent.split('\n').slice(0, range.start.line).join('\n').length + range.start.character; - const end = documentContent.split('\n').slice(0, range.end.line).join('\n').length + range.end.character; - - return documentContent.substring(start, end); -} - -export function getCurrentWord(): { word: string, range: vscode.Range, uri: vscode.Uri | undefined } { - const editor = vscode.window.activeTextEditor; - if (!editor) { - return { - word: '', range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)), - uri: undefined - }; - } - const document = editor.document; - const selection = editor.selection; - if (!selection.isEmpty) { - return { word: document.getText(selection), range: selection, uri: document.uri }; - } - const range = document.getWordRangeAtPosition(selection.active); - if (!range) { - return { word: '', range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)), uri: document.uri }; - } - return { word: document.getText(range), range: range, uri: document.uri }; -} - -export function getCurrentDocument() { - const editor = vscode.window.activeTextEditor; - if (editor === undefined) { - return undefined; - } - return editor.document; -} - -export function getCurrentDocumentFilePath() { - let document = getCurrentDocument(); - if (document) { - if (document.uri.fsPath) { - if (fs.existsSync(document.uri.fsPath)) { - return document.uri.fsPath; - } - } - } - return undefined; -} - -export async function gotoFile(uri: vscode.Uri, range?: vscode.Range): Promise { - // open a document - if (!fs.existsSync(uri.fsPath)) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showErrorMessage(`${uri.fsPath} not found`); - return; - } - - let f = await openTextDocument(uri); - let option: vscode.TextDocumentShowOptions = { - preserveFocus: true, - preview: true, - selection: range, - viewColumn: vscode.ViewColumn.Active - }; - // open an editor - let e = await vscode.window.showTextDocument(f, option); -} - -export async function openTextDocumentInRange(uri: vscode.Uri, range: vscode.Range) { - let f = await openTextDocument(uri); - let option: vscode.TextDocumentShowOptions = { - preserveFocus: false, - preview: true, - selection: range, - viewColumn: vscode.ViewColumn.Active - }; - // open an editor - let e = await vscode.window.showTextDocument(f, option); - -} - -export async function openFileSide(uri: vscode.Uri, range?: vscode.Range): Promise { - // open a document - if (!fs.existsSync(uri.fsPath)) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showErrorMessage(`${uri.fsPath} not found`); - return; - } - - let f = await openTextDocument(uri); - let option: vscode.TextDocumentShowOptions = { - preserveFocus: false, - preview: true, - selection: range, - viewColumn: vscode.ViewColumn.Two - }; - // open an editor - let e = await vscode.window.showTextDocument(f, option); -} - -var currentFile = ""; -export function openedFilePath() { - // Get opened file - var openedFilePath = vscode.window.activeTextEditor?.document.uri.fsPath; - if (openedFilePath === undefined) { return undefined; } - - if (currentFile === openedFilePath) { - return undefined; - } - - currentFile = openedFilePath; - return currentFile; -} - -export function getOpenFilePath() { - // Get opened file - var openedFilePath = vscode.window.activeTextEditor?.document.uri.fsPath; - if (openedFilePath === undefined) { return undefined; } - return openedFilePath; -} - -export function getStaticPath(file: string) { - - return path.join(gExtensionContext.asAbsolutePath("static"), file); -} - - -/* -This returns the real absolute path of inputPath with Upper and lower case. -Use this before showing some path in GUI -*/ -export function getRealPath(inputPath: string) { - let fullPath = inputPath; - if (!path.isAbsolute(fullPath)) { - fullPath = path.resolve(gWorkspacePath, fullPath); - } - if (!fs.existsSync(fullPath)) { - return ""; - } - let fullRealPath = fs.realpathSync.native(fullPath); - return fullRealPath; -} - - - -/* -This solves the problem where some inconsistencies in the make file are found: -signs like /, \, .. or upper/lower case paths. -Use this before doing something with a path -*/ -export function normalizePath(inputPath: string): string { - try { - var returnPath = ""; - - // As this function is expensive. Lets check if inputPath has already been resolved - if (normalizeCache.has(inputPath)) { - return normalizeCache.get(inputPath); - } - - let fullPath = inputPath; - if (!path.isAbsolute(fullPath)) { - fullPath = path.resolve(gWorkspacePath, fullPath); - } - let nativePath = fs.realpathSync.native(fullPath); - let substRealPath; - // In case user is using subst. Replace workspace path - substRealPath = path.join(gWorkspacePath, nativePath.slice(nativePath.length - path.relative(gWorkspacePath, fullPath).length)); - - //If file doesnt exist return the native path as is - if (!fs.existsSync(substRealPath)) { - returnPath = nativePath; - } else { - // subst path exist, then return subst path - returnPath = substRealPath; - } - } catch (error) { - gDebugLog.warning(`NormalizePath: ${error}`); - returnPath = ""; - } - normalizeCache.set(inputPath, returnPath); - return returnPath; - -} - -export function pathCompare(path1: string, path2: string) { - if (normalizePath(path1) === normalizePath(path2)) { - return true; - } - return false; -} - - -export async function createVirtualFile(title: string, content: string, languageId = "") { - let scheme = "untitle"; - const myProvider = new (class implements vscode.TextDocumentContentProvider { - provideTextDocumentContent(uri: vscode.Uri): string { - return content; - } - })(); - vscode.workspace.registerTextDocumentContentProvider(scheme, myProvider); - let uri = vscode.Uri.parse(`${scheme}:${title}`); - let doc = await vscode.workspace.openTextDocument(uri); // calls back into the provider - return doc; -} - -export async function showVirtualFile(title: string, content: string, languageId = "") { - - let doc = await createVirtualFile(title, content, languageId); - await vscode.window.showTextDocument(doc, { preview: false }); - if (languageId !== "") { - await vscode.languages.setTextDocumentLanguage(doc, languageId); - } -} - -export async function openTextDocument(uri: vscode.Uri) { - try { - let f = await vscode.workspace.openTextDocument(uri); - return f; - } catch (error) { - - gDebugLog.error(`Problem opening ${uri.fsPath}:\n ${error}`); - return await createVirtualFile("error", ""); - } - - -} - - - - - -export async function copyToClipboard(data:string, message:string="Data copied to clipboard"){ - await vscode.env.clipboard.writeText(data); - // eslint-disable-next-line @typescript-eslint/no-floating-promises - vscode.window.showInformationMessage("📋" + " " + message); -} - - - - -export function isWorkspacePath(p: string) { - for (const folder of vscode.workspace.workspaceFolders!) { - const relativePath = path.relative(folder.uri.fsPath, p); - - if(!relativePath.includes("..") && relativePath !== p){ - return true; - } - } - return false; - -} - -export function trimSpaces(text: string) { - return text.replace(/\s+/g, ' ').trim(); -} - -export function split(text: string, sepparator: string, limit: number, defaultValue: string = "") { - let temp = text.split(sepparator).map((x) => { return x.trim(); }); - let sText: string[] = []; - for (const x of temp) { - if (x.length === 0) { continue; } - sText.push(x); - } - - - - // If length its correct - if (sText.length === limit) { return sText; } - - if (sText.length > limit) { - // limit length - let a = sText.slice(limit - 1).join(sepparator); - let x = [...sText.slice(0, limit - 1), ...[a]]; - return x; - } - - // Extend length - let pending = limit - sText.length; - let arr = new Array(pending).fill(defaultValue); - return [...sText, ...arr]; - -} - -/** - * Fetches all symbols from a given file. - * - * @param fileUri - The URI of the file from which to retrieve symbols. - * @returns A promise that resolves to an array of DocumentSymbol objects representing the symbols in the file. - * @throws An error if the document cannot be opened or symbols cannot be fetched. - */ -export async function getAllSymbols(fileUri: vscode.Uri) { - const document = await vscode.workspace.openTextDocument(fileUri); - if (document) { - const symbols = await vscode.commands.executeCommand( - 'vscode.executeDocumentSymbolProvider', - fileUri - ); - return symbols || []; - } - return []; -} - - -export async function getSymbolAtLocation(uri: vscode.Uri, location: vscode.Location): Promise { - const symbols = await getAllSymbols(uri); - let returnSymbol = undefined; - for (const symbol of symbols) { - if (symbol.range.intersection(location.range)) { - returnSymbol = symbol; - } - } - - return returnSymbol; -} - - - -export function readLines(filePath: string) { - gDebugLog.debug(`readLines: ${filePath}`); - if (!fs.existsSync(filePath)) { - gDebugLog.warning(`readlines: File doesnt exist: ${filePath}`); - return []; - } - - return fs.readFileSync(filePath).toString().split(/\r?\n/); -} - -export function readFile(filePath: string) { - return fs.readFileSync(filePath).toString(); -} - - -/* -This returns the real absolute path of inputPath with Upper and lower case. -Use this before showing some path in GUI -*/ -export function getRealPathRelative(inputPath: string) { - inputPath = getRealPath(inputPath); - return path.relative(gWorkspacePath, inputPath); -} - -export function makeRelativeToWs(filePath: string) { - if (!path.isAbsolute(filePath)) { - return filePath; - } - return getRealPathRelative(filePath); -} - -export async function runWithProgress(title: string, func: Function) { - return vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: title, - cancellable: true - }, async (progress, reject) => { - let data = await func(); - return data; - }); -} - -export function createRange(lineStart: number = 0, lineEnd: number = 0, endLength: number = 0) { - return new vscode.Range( - new vscode.Position(lineStart, 0), - new vscode.Position(lineEnd, endLength) - ); - -} - -export async function itsPcdSelected(document: vscode.TextDocument, position: vscode.Position) { - let pcdRange = document.getWordRangeAtPosition(position, REGEX_PCD); - if (pcdRange) { - let pcd = document.getText(pcdRange).trim(); - let [namespace, name] = split(pcd, ".", 2); - let wps = await gEdkWorkspaces.getWorkspace(document.uri); - if (wps.length) { - for (const wp of wps) { - let pcdsList = wp.getPcds(namespace); - if (pcdsList === undefined) { continue; } - let resultPcd = pcdsList.get(name); - if (resultPcd) { - return resultPcd; - } - } - } - } -} - - - - -var profileStartTime: number; -var profileEndTime: number; -export function profileStart() { - profileStartTime = new Date().getTime(); - gDebugLog.debug("PROFILE START"); -} - -export function profileEnd() { - profileEndTime = new Date().getTime(); - let diff = profileEndTime - profileStartTime; - gDebugLog.debug(`PROFILE END: ${diff}`); -} - - -export async function closeFileIfOpened(filePath: string) { - const openEditors = vscode.window.visibleTextEditors; - for (const editor of openEditors) { - if (editor.document.uri.fsPath === filePath) { - await vscode.window.showTextDocument(editor.document); - await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); - break; - } - } -} - - -export function delay(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); -} - - - - -export async function isFileEdkLibrary(uri: vscode.Uri) { - let thisDocument = await openTextDocument(uri); - if (thisDocument.languageId !== "edk2_inf") { - gDebugLog.error(`isAlibrary: ${uri.fsPath} is not a INF file`); - return false; - } - - if (thisDocument.getText().match(/^\s*library_class\s*=/gmi)) { - return true; - } - return false; -} - - -/** - * Retrieves a list of files in the specified directory. - * @param {string} dir - The directory to search for files. - * @returns {Promise} The list of file paths. - */ -export async function listFiles(dir: string): Promise { - const files = fs.readdirSync(dir); - let filelist: string[] = []; - for (const file of files) { - const filepath = path.join(dir, file); - filelist.push(filepath); - } - return filelist; -} - -/** - * Recursively list all files in a directory using ripgrep. - * - * @param {string} dir - The directory to start listing files from. - * @returns {Promise} - An array of file paths relative to `dir`. - */ -export async function listFilesRecursive(dir: string): Promise { - const pattern = new vscode.RelativePattern(dir, '**/*'); - const uris = await vscode.workspace.findFiles(pattern); - gDebugLog.debug(`listFilesRecursive: ${uris.length} files found in ${dir}`); - return uris.map(uri => path.relative(dir, uri.fsPath)); -} - -export default function getCurrentVersion(): string { - const packageJsonPath = path.join(__dirname, '..', 'package.json'); - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); - return packageJson.version; -} - -export function getDocsUrl():string{ - const packageJsonPath = path.join(__dirname, '..', 'package.json'); - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); - return packageJson.homepage; -} - - -export function findClosestCommonDirectory(paths: string[]): string { - if (paths.length === 0){ - return ""; - } - - let commonPath = paths[0]; - for (let i = 1; i < paths.length; i++) { - commonPath = getCommonPath(commonPath, paths[i]); - if (commonPath === ''){ - break; - } - } - return commonPath; -} - -export function getCommonPath(path1: string, path2: string): string { - const path1Parts = path1.split(path.sep); - const path2Parts = path2.split(path.sep); - const length = Math.min(path1Parts.length, path2Parts.length); - - let commonParts = []; - for (let i = 0; i < length; i++) { - if (path1Parts[i] === path2Parts[i]) { - commonParts.push(path1Parts[i]); - } else { - break; - } - } - return commonParts.join(path.sep); -} \ No newline at end of file diff --git a/src/workspaceTree/WorkspaceTreeProvider.ts b/src/workspaceTree/WorkspaceTreeProvider.ts deleted file mode 100644 index 4e90c56..0000000 --- a/src/workspaceTree/WorkspaceTreeProvider.ts +++ /dev/null @@ -1,861 +0,0 @@ -import * as vscode from 'vscode'; -import * as path from 'path'; -import { EdkWorkspace, IncludeNode, InfDsc } from '../index/edkWorkspace'; -import { getParser } from '../edkParser/parserFactory'; -import { EdkSymbol } from '../symbols/edkSymbols'; -import { Edk2SymbolType } from '../symbols/symbolsType'; -import { edkWorkspaceTreeView, gConfigAgent, gEdkWorkspaces } from '../extension'; -import { DiagnosticManager, EdkDiagnosticCodes } from '../diagnostics'; - -// ─── DSC symbol types available for filtering ───────────────────────────────── - -export const DSC_FILTER_TYPES: { type: Edk2SymbolType; label: string; description: string }[] = [ - { type: Edk2SymbolType.dscDefine, label: 'Defines', description: 'dscDefine' }, - { type: Edk2SymbolType.dscLibraryDefinition, label: 'Library classes', description: 'dscLibraryDefinition' }, - { type: Edk2SymbolType.dscModuleDefinition, label: 'Components', description: 'dscModuleDefinition' }, - { type: Edk2SymbolType.dscSection, label: 'Sections', description: 'dscSection' }, - { type: Edk2SymbolType.dscBuildOptionsSection, label: 'Build options', description: 'dscBuildOptionsSection' }, - { type: Edk2SymbolType.dscBuildOption, label: 'Build option entries', description: 'dscBuildOption' }, - { type: Edk2SymbolType.dscPcdDefinition, label: 'PCDs', description: 'dscPcdDefinition' }, - { type: Edk2SymbolType.dscInclude, label: 'Include directives', description: 'dscInclude' }, - { type: Edk2SymbolType.showInactiveNodes, label: 'Inactive elements', description: 'Show elements inside inactive !if/!else blocks' }, -]; - -// Structural / container types that are always visible in the tree regardless of -// the user's filter selection. These types exist only to group children and -// filtering them out would hide all their descendants. -const STRUCTURAL_TYPES = new Set([ - Edk2SymbolType.dscComponentSubSection, -]); - -/** Returns true when a symbol type should be shown in the tree. */ -function isTypeVisible(type: Edk2SymbolType, activeFilters: Set): boolean { - return activeFilters.has(type) || STRUCTURAL_TYPES.has(type); -} - -/** - * Returns true when the symbol's selection range falls inside any of the - * grayout (inactive conditional) ranges for its file. - */ -function isSymbolInactive(symbol: EdkSymbol, fileUri: vscode.Uri, workspace: EdkWorkspace | undefined): boolean { - if (!workspace) { return false; } - const grayoutRanges = workspace.getGrayoutRangeByUri(fileUri); - const symLine = symbol.selectionRange.start.line; - return grayoutRanges.some(r => symLine >= r.start.line && symLine <= r.end.line); -} - -/** - * If the symbol has a duplicateDefine or duplicateStatement diagnostic, - * returns the location of the definition that overwrites it (from relatedInformation). - */ -function getOverwriteLocation(symbol: EdkSymbol, fileUri: vscode.Uri): vscode.Location | undefined { - const diag = DiagnosticManager.findDiagnosticAt( - fileUri, - symbol.selectionRange.start.line, - [EdkDiagnosticCodes.duplicateDefine, EdkDiagnosticCodes.duplicateStatement] - ); - if (!diag?.relatedInformation?.length) { return undefined; } - return diag.relatedInformation[0].location; -} - -// ─── Helper: load symbols for a URI via the parser ─────────────────────────── - -async function loadSymbols(uri: vscode.Uri): Promise { - try { - const parser = await getParser(uri); - return (parser?.symbolsTree ?? []) as EdkSymbol[]; - } catch { - return []; - } -} - -// ─── Helper: collect all file URIs reachable in an include tree ─────────────── - -function collectIncludeUris(nodes: IncludeNode[], out: Set): void { - for (const node of nodes) { - out.add(node.uri.fsPath); - collectIncludeUris(node.children, out); - } -} - -/** - * Returns true when the given URI is the main DSC or any file included - * (directly or transitively) in at least one workspace of the provided list. - */ -export function isFileInWorkspaceTree(uri: vscode.Uri, workspaces: EdkWorkspace[]): boolean { - for (const ws of workspaces) { - if (ws.mainDsc.fsPath === uri.fsPath) { return true; } - const uris = new Set(); - collectIncludeUris(ws.includeTree, uris); - if (uris.has(uri.fsPath)) { return true; } - } - return false; -} - -/** - * Returns true when the given INF URI is referenced as a module or library - * in at least one loaded workspace. - * Uses the same path-suffix check that EdkWorkspace.isFileInUse() performs. - */ -export function isInfInWorkspaces(uri: vscode.Uri, workspaces: EdkWorkspace[]): boolean { - for (const ws of workspaces) { - for (const mod of ws.filesModules) { - if (uri.fsPath.includes(mod.path)) { return true; } - } - for (const lib of ws.filesLibraries) { - if (uri.fsPath.includes(lib.path)) { return true; } - } - } - return false; -} - -// ─── Tree Item: Workspace root (the main DSC) ──────────────────────────────── - -export class WorkspaceRootItem extends vscode.TreeItem { - public readonly treePath: string[]; - public readonly nodePath: string; - - constructor(public readonly workspace: EdkWorkspace, public readonly wsIndex: number) { - const label = path.basename(workspace.mainDsc.fsPath); - super(label, vscode.TreeItemCollapsibleState.Expanded); - this.id = `wsr:${wsIndex}`; - this.treePath = [label]; - this.nodePath = label; - this.description = workspace.platformName ?? ''; - this.tooltip = new vscode.MarkdownString( - `**${label}**\n\n${this.description}\n\n\`${this.nodePath}\`` - ); - this.iconPath = new vscode.ThemeIcon('file-code'); - this.contextValue = 'workspaceRoot'; - this.command = { - command: 'vscode.open', - title: 'Open DSC', - arguments: [workspace.mainDsc] - }; - } -} - -// ─── Tree Item: An !include node inside the tree ────────────────────────────── - -export class IncludeTreeItem extends vscode.TreeItem { - public readonly treePath: string[]; - public readonly nodePath: string; - public readonly inactive: boolean; - - constructor(public readonly node: IncludeNode, parentPath: string[], parentNodePath: string, inactive: boolean = false) { - const label = path.basename(node.uri.fsPath); - super(label, vscode.TreeItemCollapsibleState.Collapsed); - this.inactive = inactive; - this.treePath = [...parentPath, vscode.workspace.asRelativePath(node.uri, false)]; - this.nodePath = parentNodePath + '/' + label; - this.description = inactive - ? `${vscode.workspace.asRelativePath(node.uri, false)} (inactive)` - : vscode.workspace.asRelativePath(node.uri, false); - this.tooltip = new vscode.MarkdownString( - `**${label}**\n\n${this.description}\n\n${this.nodePath}` - ); - this.iconPath = inactive - ? new vscode.ThemeIcon('file', new vscode.ThemeColor('disabledForeground')) - : new vscode.ThemeIcon('file'); - this.contextValue = inactive ? 'includeNodeInactive' : 'includeNode'; - // Clicking jumps to the !include directive in the parent file - this.command = { - command: 'edk2code.gotoFile', - title: 'Go to !include directive', - arguments: [node.location.uri, node.location.range] - }; - } -} - -// ─── Tree Item: A document symbol (outline entry) inside a file ────────────── - -export class DocumentSymbolItem extends vscode.TreeItem { - public readonly symbolType: Edk2SymbolType; - public readonly treePath: string[]; - public readonly nodePath: string; - public readonly inactive: boolean; - public readonly overwrittenBy: vscode.Location | undefined; - - constructor( - public readonly symbol: EdkSymbol, - public readonly fileUri: vscode.Uri, - activeFilters: Set, - parentPath: string[], - public readonly parent: WorkspaceRootItem | DocumentSymbolItem | undefined, - parentNodePath: string, - inactive: boolean = false, - overwrittenBy?: vscode.Location - ) { - const visibleChildren = symbol.children.filter( - c => isTypeVisible((c as EdkSymbol).type, activeFilters) - ); - const isDscInclude = symbol.type === Edk2SymbolType.dscInclude; - super( - symbol.name, - visibleChildren.length > 0 || isDscInclude - ? vscode.TreeItemCollapsibleState.Collapsed - : vscode.TreeItemCollapsibleState.None - ); - this.inactive = inactive; - this.overwrittenBy = overwrittenBy; - this.treePath = [...parentPath, symbol.name]; - this.nodePath = parentNodePath + ' / ' + symbol.name; - // Include the parent path in the id so the same file/symbol included from - // multiple places in the tree gets a unique id for each occurrence. - const parentKey = parentPath.join('/'); - this.id = `dsi:${parentKey}:${fileUri.fsPath}:${symbol.selectionRange.start.line}:${symbol.selectionRange.start.character}`; - this.symbolType = symbol.type; - - // Build description and context based on state - const isOverwritten = !!overwrittenBy; - const isBuildable = (symbol.type === Edk2SymbolType.dscModuleDefinition); - let desc = symbol.detail || ''; - let ctx = 'symbolNode'; - if (inactive && isOverwritten) { - desc = `${this.label} (inactive, overwritten) ${desc}`.trim(); - ctx = 'symbolNodeInactiveOverwritten'; - } else if (inactive) { - desc = `${this.label} (inactive) ${desc}`.trim(); - ctx = 'symbolNodeInactive'; - } else if (isOverwritten) { - desc = `${this.label} (overwritten) ${desc}`.trim(); - ctx = 'symbolNodeOverwritten'; - } else if (isBuildable) { - ctx = 'symbolNodeBuildable'; - } - - if(ctx !== 'symbolNode' && ctx !== 'symbolNodeBuildable') { - // The label is shown with strikethrough in the tree when overwritten, so we move the original label to the description and show the overwrite status in the label instead. This keeps the label text fully visible without truncation, while still indicating the symbol's name and status. - this.label = ""; - } - - this.description = desc || undefined; - - this.tooltip = new vscode.MarkdownString( - `**${symbol.name}**\n\n${this.description ?? ''}\n\n${this.nodePath}` - ); - - if (inactive || isOverwritten) { - this.iconPath = new vscode.ThemeIcon( - EdkSymbol.iconForKind(symbol.kind).id, - new vscode.ThemeColor('disabledForeground') - ); - } else { - this.iconPath = EdkSymbol.iconForKind(symbol.kind); - } - - this.contextValue = ctx; - // Clicking navigates to the symbol's location in its file - this.command = { - command: 'edk2code.gotoFile', - title: 'Go to symbol', - arguments: [fileUri, symbol.selectionRange] - }; - } -} - -export type WorkspaceTreeNode = WorkspaceRootItem | IncludeTreeItem | DocumentSymbolItem; - -// ─── Helper: find an IncludeNode by the location of its !include directive ─── - -function findIncludeNode(nodes: IncludeNode[], location: vscode.Location): IncludeNode | undefined { - for (const node of nodes) { - if (node.location.uri.fsPath === location.uri.fsPath && - node.location.range.start.line === location.range.start.line) { - return node; - } - const found = findIncludeNode(node.children, location); - if (found) { return found; } - } - return undefined; -} - -// ─── Recursive text serializer ─────────────────────────────────────────────── - -async function resolveIncludedUri(symbol: EdkSymbol): Promise { - if (symbol.type !== Edk2SymbolType.dscInclude || !symbol.onDefinition) { - return undefined; - } - const locations = await Promise.resolve(symbol.onDefinition(symbol.parser)) as vscode.Location[] | undefined; - return locations?.[0]?.uri; -} - -async function serializeFileSymbols( - fileUri: vscode.Uri, - indent: string, - filter: Set, - expandedFiles: Set -): Promise { - const symbols = await loadSymbols(fileUri); - let out = ''; - for (const sym of symbols) { - if (isTypeVisible(sym.type, filter)) { - out += await serializeSymbol(sym, indent, filter, expandedFiles); - } - } - return out; -} - -async function serializeSymbol( - symbol: EdkSymbol, - indent: string, - filter: Set, - expandedFiles: Set -): Promise { - const line = `${indent}${symbol.name}${symbol.detail ? ' - ' + symbol.detail : ''}\n`; - let out = line; - if (symbol.type === Edk2SymbolType.dscInclude) { - const includeUri = await resolveIncludedUri(symbol); - if (!includeUri || expandedFiles.has(includeUri.fsPath)) { - return out; - } - const nextExpandedFiles = new Set(expandedFiles); - nextExpandedFiles.add(includeUri.fsPath); - out += await serializeFileSymbols(includeUri, indent + ' ', filter, nextExpandedFiles); - return out; - } - for (const child of symbol.children) { - const edkChild = child as EdkSymbol; - if (isTypeVisible(edkChild.type, filter)) { - out += await serializeSymbol(edkChild, indent + ' ', filter, expandedFiles); - } - } - return out; -} - -// ─── Helper: find the deepest filtered symbol that contains a position ──────── - -function findDeepestSymbolAt( - symbols: EdkSymbol[], - position: vscode.Position, - filter: Set -): EdkSymbol | undefined { - let best: EdkSymbol | undefined; - for (const sym of symbols) { - if (!isTypeVisible(sym.type, filter)) { continue; } - const inRange = sym.range.contains(position) || sym.selectionRange.contains(position); - if (inRange) { - best = sym; - const deeper = findDeepestSymbolAt(sym.children as EdkSymbol[], position, filter); - if (deeper) { best = deeper; } - } - } - // Fallback: if no symbol contains the position, return the one closest by line - if (!best) { - let closestDist = Infinity; - for (const sym of symbols) { - if (!isTypeVisible(sym.type, filter)) { continue; } - const dist = Math.abs(sym.selectionRange.start.line - position.line); - if (dist < closestDist) { - closestDist = dist; - best = sym; - } - } - } - return best; -} - -// ─── Tree data provider ─────────────────────────────────────────────────────── - -export class WorkspaceTreeProvider implements vscode.TreeDataProvider, vscode.TreeDragAndDropController { - private _onDidChangeTreeData = - new vscode.EventEmitter(); - readonly onDidChangeTreeData = this._onDidChangeTreeData.event; - - // ─── Drag & Drop ────────────────────────────────────────────────────────── - readonly dropMimeTypes: string[] = ['application/vnd.code.tree.workspaceview']; - readonly dragMimeTypes: string[] = ['application/vnd.code.tree.workspaceview']; - - /** Stashed source info from the last drag operation. */ - private _draggedSource: { fileUri: vscode.Uri; range: vscode.Range } | undefined; - - handleDrag( - source: readonly WorkspaceTreeNode[], - _dataTransfer: vscode.DataTransfer, - _token: vscode.CancellationToken - ): void { - const item = source.find( - (s): s is DocumentSymbolItem => s instanceof DocumentSymbolItem - ); - if (!item) { - this._draggedSource = undefined; - return; - } - this._draggedSource = { fileUri: item.fileUri, range: item.symbol.range }; - } - - async handleDrop( - target: WorkspaceTreeNode | undefined, - _dataTransfer: vscode.DataTransfer, - _token: vscode.CancellationToken - ): Promise { - const source = this._draggedSource; - this._draggedSource = undefined; - if (!source || !target) { return; } - if (!(target instanceof DocumentSymbolItem)) { return; } - - const targetRange = target.symbol.range; - - // Skip dropping onto itself - if ( - source.fileUri.fsPath === target.fileUri.fsPath && - source.range.isEqual(targetRange) - ) { - return; - } - - const sourceDoc = await vscode.workspace.openTextDocument(source.fileUri); - - // Read full lines of the source symbol - const srcStart = source.range.start.line; - const srcEnd = source.range.end.line; - let textToMove = ''; - for (let i = srcStart; i <= srcEnd; i++) { - textToMove += sourceDoc.lineAt(i).text + '\n'; - } - - // Delete range: whole lines - const deleteRange = srcEnd + 1 < sourceDoc.lineCount - ? new vscode.Range(srcStart, 0, srcEnd + 1, 0) - : new vscode.Range( - srcStart === 0 ? 0 : srcStart - 1, - srcStart === 0 ? 0 : sourceDoc.lineAt(srcStart - 1).text.length, - srcEnd, - sourceDoc.lineAt(srcEnd).text.length - ); - - // Insert right after the target symbol's last line - const targetDoc = await vscode.workspace.openTextDocument(target.fileUri); - const tgtEnd = targetRange.end.line; - let insertPos: vscode.Position; - let insertText: string; - - if (tgtEnd + 1 < targetDoc.lineCount) { - insertPos = new vscode.Position(tgtEnd + 1, 0); - insertText = textToMove; - } else { - insertPos = new vscode.Position(tgtEnd, targetDoc.lineAt(tgtEnd).text.length); - insertText = '\n' + textToMove.replace(/\n$/, ''); - } - - const edit = new vscode.WorkspaceEdit(); - edit.delete(source.fileUri, deleteRange); - edit.insert(target.fileUri, insertPos, insertText); - await vscode.workspace.applyEdit(edit); - - // Refresh tree and reveal the target symbol - this.refresh(); - const tgtPosition = target.symbol.selectionRange.start; - await this.revealLocation(target.fileUri, tgtPosition, edkWorkspaceTreeView); - } - - private _activeIndex: number = 0; - - /** Which DSC symbol types are currently visible. Loaded from config; defaults to all. */ - private _activeFilters: Set = (() => { - const saved = gConfigAgent.getWorkspaceTreeFilters(); - if (saved && saved.length > 0) { - return new Set(saved as Edk2SymbolType[]); - } - return new Set(DSC_FILTER_TYPES.map(f => f.type)); - })(); - - /** - * When set, the tree only shows nodes whose `nodePath` is in this set. - * Used by the "Search workspace tree" command to display only the path - * leading to a selected node. `undefined` means no path filter is active. - */ - private _searchFilter: Set | undefined; - - get activeIndex(): number { - return this._activeIndex; - } - - get isSearchFilterActive(): boolean { - return this._searchFilter !== undefined; - } - - /** Filter the children list against the active search filter (if any). */ - private _applySearchFilter(items: T[]): T[] { - if (!this._searchFilter) { return items; } - const filter = this._searchFilter; - const filtered = items.filter(i => filter.has(i.nodePath)); - // Force-expand surviving nodes so the path to the target is visible. - for (const item of filtered) { - if (item.collapsibleState === vscode.TreeItemCollapsibleState.Collapsed) { - item.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; - } - } - return filtered; - } - - /** Clear the search-path filter and refresh the tree. */ - clearSearchFilter(): void { - if (!this._searchFilter) { return; } - this._searchFilter = undefined; - void vscode.commands.executeCommand('setContext', 'edk2code.workspaceTreeSearchActive', false); - this._onDidChangeTreeData.fire(); - } - - refresh(): void { - // Clamp index in case workspaces were removed - const max = Math.max(0, gEdkWorkspaces.workspaces.length - 1); - this._activeIndex = Math.min(this._activeIndex, max); - this._onDidChangeTreeData.fire(); - } - - /** - * Switch the displayed workspace and refresh the view. - */ - selectWorkspace(index: number): void { - this._activeIndex = index; - this._onDidChangeTreeData.fire(); - } - - /** - * Show a multi-select Quick Pick to toggle which DSC symbol types are shown. - */ - async showFilterPicker(): Promise { - type FilterPickItem = vscode.QuickPickItem & { type: Edk2SymbolType }; - const items: FilterPickItem[] = DSC_FILTER_TYPES.map(f => ({ - label: f.label, - description: f.description, - picked: this._activeFilters.has(f.type), - type: f.type - })); - - const picked = await vscode.window.showQuickPick(items, { - canPickMany: true, - placeHolder: 'Select symbol types to show', - title: 'EDK2: Filter workspace symbols' - }); - - // Cancelled → leave filter unchanged - if (picked === undefined) { return; } - - this._activeFilters = new Set(picked.map(p => p.type)); - gConfigAgent.setWorkspaceTreeFilters([...this._activeFilters]); - this._onDidChangeTreeData.fire(); - } - - /** - * Serialize the whole displayed workspace tree to an indented string. - */ - async serializeTree(): Promise { - const ws = gEdkWorkspaces.workspaces[this._activeIndex]; - if (!ws) { return ''; } - - const rootLabel = path.basename(ws.mainDsc.fsPath); - const rel = vscode.workspace.asRelativePath(ws.mainDsc, false); - let out = `${rootLabel} (${rel})\n`; - out += await serializeFileSymbols(ws.mainDsc, ' ', this._activeFilters, new Set([ws.mainDsc.fsPath])); - return out; - } - - getTreeItem(element: WorkspaceTreeNode): vscode.TreeItem { - return element; - } - - async getChildren(element?: WorkspaceTreeNode): Promise { - const workspaces = gEdkWorkspaces.workspaces; - if (workspaces.length === 0) { - return []; - } - - const ws = workspaces[this._activeIndex]; - - // Root level: the single WorkspaceRootItem for the active workspace - if (!element) { - if (!ws) { return []; } - return this._applySearchFilter([new WorkspaceRootItem(ws, this._activeIndex)]); - } - - const showInactive = this._activeFilters.has(Edk2SymbolType.showInactiveNodes); - - // Under the workspace root: symbols of the main DSC - if (element instanceof WorkspaceRootItem) { - const symbols = await loadSymbols(element.workspace.mainDsc); - return this._applySearchFilter(symbols - .filter(s => isTypeVisible(s.type, this._activeFilters)) - .map(s => new DocumentSymbolItem(s, element.workspace.mainDsc, this._activeFilters, element.treePath, element, element.nodePath, - isSymbolInactive(s, element.workspace.mainDsc, ws), - getOverwriteLocation(s, element.workspace.mainDsc))) - .filter(s => showInactive || !s.inactive)); - } - - // Under an include node: symbols of that file only - if (element instanceof IncludeTreeItem) { - const inactive = element.inactive; - const symbols = await loadSymbols(element.node.uri); - return this._applySearchFilter(symbols - .filter(s => isTypeVisible(s.type, this._activeFilters)) - .map(s => new DocumentSymbolItem(s, element.node.uri, this._activeFilters, element.treePath, undefined, element.nodePath, - inactive || isSymbolInactive(s, element.node.uri, ws), - getOverwriteLocation(s, element.node.uri))) - .filter(s => showInactive || !s.inactive)); - } - - // Under a symbol: for !include directives expand into the included file; - // for all other symbols expand their parsed children. - if (element instanceof DocumentSymbolItem) { - if (element.symbolType === Edk2SymbolType.dscInclude) { - if (ws) { - const node = findIncludeNode(ws.includeTree, element.symbol.location); - if (node) { - const symbols = await loadSymbols(node.uri); - return this._applySearchFilter(symbols - .filter(s => isTypeVisible(s.type, this._activeFilters)) - .map(s => new DocumentSymbolItem(s, node.uri, this._activeFilters, element.treePath, element, element.nodePath, - element.inactive || isSymbolInactive(s, node.uri, ws), - getOverwriteLocation(s, node.uri))) - .filter(s => showInactive || !s.inactive)); - } - } - } - return this._applySearchFilter((element.symbol.children as EdkSymbol[]) - .filter(c => isTypeVisible(c.type, this._activeFilters)) - .map(child => new DocumentSymbolItem(child, element.fileUri, this._activeFilters, element.treePath, element, element.nodePath, - element.inactive || isSymbolInactive(child, element.fileUri, ws), - getOverwriteLocation(child, element.fileUri))) - .filter(s => showInactive || !s.inactive)); - } - - return []; - } - - getParent(element: WorkspaceTreeNode): vscode.ProviderResult { - if (element instanceof WorkspaceRootItem) { return undefined; } - if (element instanceof DocumentSymbolItem) { return element.parent; } - return undefined; - } - - /** - * Reveal the tree node that best matches the symbol at the cursor in the active editor. - */ - async revealActiveEditor(treeView: vscode.TreeView): Promise { - const editor = vscode.window.activeTextEditor; - if (!editor) { - void vscode.window.showInformationMessage('No active editor.'); - return; - } - await this.revealLocation(editor.document.uri, editor.selection.active, treeView); - } - - /** - * Reveal the tree node that best matches the symbol at a specific location. - */ - async revealLocation( - uri: vscode.Uri, - position: vscode.Position, - treeView: vscode.TreeView - ): Promise { - // Load symbols for the file and find the deepest one at the position - const symbols = await loadSymbols(uri); - if (symbols.length === 0) { - void vscode.window.showInformationMessage('No EDK2 symbols found in the active file.'); - return; - } - - const target = findDeepestSymbolAt(symbols, position, this._activeFilters); - if (!target) { - void vscode.window.showInformationMessage('No EDK2 symbol found at the cursor position.'); - return; - } - - // Traverse the tree to find the matching DocumentSymbolItem - const rootItems = await this.getChildren(undefined); - for (const root of rootItems) { - const found = await this._findItemForSymbol(root, uri, target); - if (found) { - await treeView.reveal(found, { select: true, focus: false, expand: true }); - return; - } - } - - void vscode.window.showInformationMessage('Symbol not found in the workspace tree.'); - } - - /** - * Reveal an INF file's DSC declaration in the workspace tree. - */ - async revealInfInTree( - infUri: vscode.Uri, - treeView: vscode.TreeView - ): Promise { - const wps = await gEdkWorkspaces.getWorkspace(infUri); - let declarations: InfDsc[] = []; - for (const wp of wps) { - declarations = declarations.concat(await wp.getDscDeclaration(infUri)); - } - if (declarations.length) { - const decl = declarations[0]; - await this.revealLocation(decl.location.uri, decl.location.range.start, treeView); - } - } - - /** - * Open an input box where the user types a query. The workspace tree is - * filtered live so that only paths leading to nodes matching the query - * remain visible. A toggle button switches between case-insensitive - * substring matching and regular expression matching. The filter can - * later be cleared via `clearSearchFilter()`. - */ - async searchTree(treeView: vscode.TreeView): Promise { - type CollectedNode = { node: WorkspaceTreeNode; chain: string[]; haystack: string }; - - // Always start the search against the unfiltered tree. - const previousFilter = this._searchFilter; - this._searchFilter = undefined; - // Refresh the tree so the input-box-driven filter starts from the full tree. - if (previousFilter) { - this._onDidChangeTreeData.fire(); - } - - // Collect every node and its ancestor chain (inclusive of itself). - const allNodes: CollectedNode[] = []; - const collect = async (parent: WorkspaceTreeNode | undefined, chain: string[]): Promise => { - const children = await this.getChildren(parent); - for (const child of children) { - const label = child instanceof DocumentSymbolItem ? child.symbol.name - : child instanceof IncludeTreeItem ? path.basename(child.node.uri.fsPath) - : (child as WorkspaceRootItem).label as string; - const description = child.description as string | undefined; - const childChain = [...chain, child.nodePath]; - const haystack = `${label}\n${description ?? ''}`; - allNodes.push({ node: child, chain: childChain, haystack }); - await collect(child, childChain); - } - }; - - await vscode.window.withProgress( - { location: { viewId: 'workspaceView' } }, - async () => { await collect(undefined, []); } - ); - - if (allNodes.length === 0) { - this._searchFilter = previousFilter; - void vscode.window.showInformationMessage('No nodes in the workspace tree.'); - return; - } - - const input = vscode.window.createInputBox(); - input.title = 'EDK2: Search workspace tree'; - input.placeholder = 'Type to filter (case-insensitive). Toggle .* to use regex.'; - input.prompt = 'Tree updates live. Press Enter to keep the filter, Esc to cancel.'; - - const regexButtonOff: vscode.QuickInputButton = { - iconPath: new vscode.ThemeIcon('regex'), - tooltip: 'Use Regular Expression (off)' - }; - const regexButtonOn: vscode.QuickInputButton = { - iconPath: new vscode.ThemeIcon('regex'), - tooltip: 'Use Regular Expression (on)' - }; - let useRegex = false; - input.buttons = [regexButtonOff]; - - // Track whether the user accepted (Enter) so onDidHide knows whether to revert. - let accepted = false; - - const applyFilter = (value: string): void => { - if (!value) { - // Empty input → no filter while typing. - this._searchFilter = undefined; - input.validationMessage = undefined; - void vscode.commands.executeCommand('setContext', 'edk2code.workspaceTreeSearchActive', false); - this._onDidChangeTreeData.fire(); - return; - } - - let predicate: (s: string) => boolean; - if (useRegex) { - let rx: RegExp; - try { - rx = new RegExp(value, 'i'); - } catch (e) { - input.validationMessage = `Invalid regex: ${(e as Error).message}`; - return; - } - input.validationMessage = undefined; - predicate = (s) => rx.test(s); - } else { - input.validationMessage = undefined; - const needle = value.toLowerCase(); - predicate = (s) => s.toLowerCase().includes(needle); - } - - // Keep every nodePath that's part of an ancestor chain leading to a match. - const keep = new Set(); - for (const item of allNodes) { - if (predicate(item.haystack)) { - for (const p of item.chain) { keep.add(p); } - } - } - - this._searchFilter = keep.size > 0 ? keep : new Set(['__no_match__']); - void vscode.commands.executeCommand('setContext', 'edk2code.workspaceTreeSearchActive', true); - this._onDidChangeTreeData.fire(); - }; - - input.onDidChangeValue(applyFilter); - input.onDidTriggerButton(btn => { - if (btn === regexButtonOff || btn === regexButtonOn) { - useRegex = !useRegex; - input.buttons = [useRegex ? regexButtonOn : regexButtonOff]; - applyFilter(input.value); - } - }); - - await new Promise(resolve => { - input.onDidAccept(() => { - accepted = true; - input.hide(); - }); - input.onDidHide(() => { - resolve(); - }); - input.show(); - }); - input.dispose(); - - if (!accepted) { - // User cancelled (Esc) → restore the previous filter state. - this._searchFilter = previousFilter; - void vscode.commands.executeCommand( - 'setContext', - 'edk2code.workspaceTreeSearchActive', - this._searchFilter !== undefined - ); - this._onDidChangeTreeData.fire(); - return; - } - - // Accepted: keep whatever filter the live preview produced. - if (!this._searchFilter) { - // Empty query at acceptance → no filter active. - void vscode.commands.executeCommand('setContext', 'edk2code.workspaceTreeSearchActive', false); - } - } - - /** Recursively walk the tree to find a DocumentSymbolItem matching (fileUri, targetSymbol). */ - private async _findItemForSymbol( - parent: WorkspaceTreeNode, - fileUri: vscode.Uri, - targetSymbol: EdkSymbol - ): Promise { - const children = await this.getChildren(parent); - for (const child of children) { - if ( - child instanceof DocumentSymbolItem && - child.fileUri.fsPath === fileUri.fsPath && - child.symbol.selectionRange.start.line === targetSymbol.selectionRange.start.line && - child.symbol.selectionRange.start.character === targetSymbol.selectionRange.start.character - ) { - return child; - } - const found = await this._findItemForSymbol(child, fileUri, targetSymbol); - if (found) { return found; } - } - return undefined; - } -} diff --git a/static/acpiHelp.json b/static/acpiHelp.json deleted file mode 100644 index ebcc7b9..0000000 --- a/static/acpiHelp.json +++ /dev/null @@ -1,3586 +0,0 @@ -[ - { - "title": "AccessAs (Change Field Unit Access)", - "syntax": "AccessAs (AccessType, AccessAttribute)\nAccessAs (AccessType, AccessAttribute (AccessLength))", - "arguments": "AccessType is an AccessTypeKeyword that specifies the type of access desired (ByteAcc, WordAcc, etc.). AccessAttribute is an optional argument of type AccessAttributeKeyword that specifies additional protocols to be used, such as AttribQuick, AttribSendReceive, etc. AccessLength is a required argument for some of the Access Attributes.", - "description": "The AccessAs operator is used within a FieldList to specify the Access Type, Access Attributes, and Access Length for the remaining FieldUnits within the list (or until another AccessAs operator is encountered.) It allows FieldUnits to have different access types within a single Field definition.\nSupported AccessTypes:\n\u2022 AnyAcc\n\u2022 ByteAcc\n\u2022 WordAcc\n\u2022 DwordAcc\n\u2022 QWordAcc\n\u2022 BufferAcc\nSupported simple AccessAttributes (with SMBus synonyms):\n\u2022 AttribQuick (SMBQuick)\n\u2022 AttribSendReceive (SMBSendReceive)\n\u2022 AttribByte (SMBByte)\n\u2022 AttribWord (SMBWord)\n\u2022 AttribBlock (SMBBlock)\n\u2022 AttribProcessCall (SMBProcessCall)\n\u2022 AttribBlockProcessCall (SMBBlockProcessCall)\nAccess Attributes that require an AccessLength argument:\n\u2022 AttribBytes (AccessLength)\n\u2022 AttribRawBytes (AccessLength)\n\u2022 AttribRawProcessBytes (AccessLength)", - "example": "" - }, - { - "title": "Acquire (Acquire a Mutex)", - "syntax": "Acquire (SyncObject, TimeoutValue) => Boolean", - "arguments": "SynchObject must be a mutex synchronization object. TimeoutValue is evaluated as an Integer.", - "description": "Ownership of the Mutex is obtained. If the Mutex is already owned by a different invocation, the current execution thread is suspended until the owner of the Mutex releases it or until at least TimeoutValue milliseconds have elapsed. A Mutex can be acquired more than once by the same invocation.\nNote: For Mutex objects referenced by a _DLM object, the host OS may also contend for ownership.\nThis operation returns True if a timeout occurred and the mutex ownership was not acquired. A TimeoutValue of 0xFFFF (or greater) indicates that there is no timeout and the operation will wait indefinitely.", - "example": "" - }, - { - "title": "Add (Integer Add)", - "syntax": "Add (Addend1, Addend2, Result) => Integer\nResult = Addend1 + Addend2 => Integer\nResult += Addend => Integer", - "arguments": "Addend1 and Addend2 are evaluated as Integers.", - "description": "The operands are added and the result is optionally stored into Result. Overflow conditions are ignored and the result of overflows simply loses the most significant bits.", - "example": "" - }, - { - "title": "Alias (Declare Name Alias)", - "syntax": "Alias (SourceObject, AliasObject)", - "arguments": "SourceObject is any named object. AliasObject is a NameString.", - "description": "Creates a new object named AliasObject that refers to and acts exactly the same as SourceObject.\nAliasObject is created as an alias of SourceObject in the namespace. The SourceObject name must already exist in the namespace. If the alias is to a name within the same definition block, the SourceObject name must be logically ahead of this definition in the block.", - "example": "The following example shows the use of an Alias term:\nAlias (\\SUS.SET.EVEN, SSE)" - }, - { - "title": "And (Integer Bitwise And)", - "syntax": "And (Source1, Source2, Result) => Integer\nResult = Source1 & Source2 => Integer\nResult &= Source => Integer", - "arguments": "Source1 and Source2 are evaluated as Integers.", - "description": "A bitwise AND is performed and the result is optionally stored into Result.", - "example": "" - }, - { - "title": "Argx (Method Argument Data Objects)", - "syntax": "Arg0 | Arg1 | Arg2 | Arg3 | Arg4 | Arg5 | Arg6", - "arguments": "", - "description": "Up to 7 argument-object references can be passed to a control method. On entry to a control method, only the argument objects that are passed are usable.", - "example": "" - }, - { - "title": "BankField (Declare Bank/Data Field)", - "syntax": "BankField (RegionName, BankName, BankValue, AccessType, LockRule, UpdateRule) {FieldUnitList}", - "arguments": "RegionName is evaluated as a Namestring, and is the name of the host Operation Region.\nBankName is evaluated as a Namestring, and is the name of the bank selection register.\nBankValue is the bank selection ID (Integer) that is written to the BankName register before the FieldUnitList is accessed.\nThe AccessType, LockRule, UpdateRule, and FieldUnitList are the same format as the Field operator.", - "description": "Accessing the contents of a banked field data object will occur automatically through the proper bank setting, with synchronization occurring on the operation region that contains the BankName data variable, and on the Global Lock if specified by the LockRule.\nThis operator creates data field objects. The contents of the created objects are obtained by a reference to a bank selection register.\nThis encoding is used to define named data field objects whose data values are fields within a larger object selected by a bank-selected register.", - "example": "The following is a block of ASL sample code using BankField:\n\u2022 Creates a 4-bit bank-selected register in system I/O space.\n\u2022 Creates overlapping fields in the same system I/O space that are selected via the bank register.\n//\n// Define a 256-byte operational region in SystemIO space\n// and name it GIO0\nOperationRegion (GIO0, SystemIO, 0x125, 0x100)\n// Create some fields in GIO including a 4-bit bank select register\nField (GIO0, ByteAcc, NoLock, Preserve) {\n GLB1, 1,\n GLB2, 1,\n Offset (1), // Move to offset for byte 1\n BNK1, 4\n}\n// Create FET0 & FET1 in bank 0 at byte offset 0x30\nBankField (GIO0, BNK1, 0, ByteAcc, NoLock, Preserve) {\n Offset (0x30), \n FET0, 1,\n FET1, 1\n}\n // Create BLVL & BAC in bank 1 at the same offset\nBankField (GIO0, BNK1, 1, ByteAcc, NoLock, Preserve) {\n Offset (0x30),\n BLVL, 7,\n BAC, 1\n}" - }, - { - "title": "Break (Break from While)", - "syntax": "Break", - "arguments": "", - "description": "Break causes execution to continue immediately following the innermost enclosing While or Switch scope, in the current Method. If there is no enclosing While or Switch within the current Method, a fatal error is generated.\nCompatibility Note: In ACPI 1.0, the Break operator continued immediately following the innermost\n\u201ccode package.\u201d Starting in ACPI 2.0, the Break operator was changed to exit the innermost \u201cWhile\u201d or \u201cSwitch\u201d package. This should have no impact on existing code, since the ACPI 1.0 definition was, in practice, useless.", - "example": "" - }, - { - "title": "BreakPoint (Execution Break Point)", - "syntax": "BreakPoint", - "arguments": "", - "description": "Used for debugging, the Breakpoint opcode stops the execution and enters the AML debugger. In the non-debug version of the AML interpreter, BreakPoint is equivalent to Noop.", - "example": "" - }, - { - "title": "Buffer (Declare Buffer Object)", - "syntax": "Buffer (BufferSize) {Initializer} => Buffer", - "arguments": "Declares a Buffer of optional size BufferSize and an optional initial value of Initializer. The Initializer is must be either a ByteList or a String.", - "description": "The optional BufferSize argument specifies the size of the buffer and an optional initial value of the buffer is specified via the Initializer. The initial value can be either an ASCII String or a list of byte values separated by commas. Strings are automatically null terminated with a single zero byte.\nThe relationship between the BufferSize and the Initializer is summarized by the rules below.\nIn the typical case, the BufferSize is identical to the length of the Initializer:\n Name (BUF0, Buffer(4) {0x01,0x02,0x03,0x04}) // Length = 4\nIf the BufferSize is not specified, the length of the Initializer is used as the buffer size:\n Name (BUF1, Buffer() {0,1,2,3,4,5})// Length = 6\n Name (BUF2, Buffer() {\"abcde\"}) // Length = 6\nIf the BufferSize is larger than the length of the Initializer, the BufferSize is used as the final buffer size. At runtime, the AML interpreter will automatically pad zeros to the Initializer to match the BufferSize:\n Name (BUF3, Buffer(1024) {4,5,6,7,8})// Length = 1024\n Name (BUF4, Buffer(1024) {\"abcde\"})// Length = 1024\nIf the BufferSize is smaller than the length of the Initializer, the length of the Initializer is used as the buffer size:\n Name (BUF5, Buffer(1) {5,4,3,2,1}) // Length = 5\nIf the Initializer is not specified, the AML interpreter creates a buffer containing all zeros, the length of which matches the BufferSize:\n Name (BUF6, Buffer(32} {}) // Length = 32\nIf neither the BufferSize nor the Initializer are specified, a buffer of zero length is created:\n Name (BUF7, Buffer() {}) // Length = 0", - "example": "" - }, - { - "title": "Case (Expression for Conditional Execution)", - "syntax": "Case (Value) {TermList}", - "arguments": "Value specifies an Integer, Buffer, String or Package object. TermList is a sequence of executable ASL expressions.", - "description": "Execute code based upon the value of a Switch statement.\nIf the Case Value is an Integer, Buffer or String, then control passes to the statement that matches the value of the enclosing Switch (Value). If the Case value is a Package, then control passes if any member of the package matches the Switch (Value). The Switch CaseTermList can include any number of Case instances, but no two Case Values (or members of a Value, if Value is a Package) within the same Switch statement can contain the same value.\nExecution of the statement body begins at the start of the TermList and proceeds until the end of the TermList body or until a Break or Continue operator transfers control out of the body.", - "example": "" - }, - { - "title": "Concatenate (Concatenate Data)", - "syntax": "Concatenate (Source1, Source2, Result) => Buffer or String", - "arguments": "Source1 and Source2 must each evaluate to any valid ACPI object. For the basic data object types\n(Integer, String, or Buffer), the value of the object is used in the concatenation. For all other object types (see table 19-378 below), a string object is created that contains the name (type) of the object. This string object is then concatenated according to the rules in Table 19-427.\nThe data type of Source1 dictates the required type of Source2 and the type of the result object. Source2 is implicitly converted if necessary (and possible) to match the type of Source1.", - "description": "Source2 is concatenated to Source1 and the result data is optionally stored into Result.\nTable 19-427 Concatenate Data Types\nSource1 Data Type\nSource2 Data Type (\u00e8 Converted Type)\nResult Data Type\nInteger\nInteger/String/Buffer \u00e8 Integer\nBuffer\nString\nInteger/String/Buffer/All other types \u00e8 String\nString\nBuffer\nInteger/String/Buffer/All other types \u00e8 Buffer\nBuffer\nAll other types \u00e8String\nInteger/String/Buffer/All other types \u00e8 String\nString\nFor the Source1/Integer case, a String or Buffer that cannot be implicitly converted to an Integer will generate a fatal error.\nTable 19-428 Concatenate Object Types\nData Object Type\nName\nResolved to Value\n1\nInteger\nInteger value of the object\n2\nString\nString value of the object\n3\nBuffer\nBuffer value of the object\n \n \n \nOther Object Types\nName\nResolved to String\n0\nUninitialized\n\"[Uninitialized Object]\"\n4\nPackage\n\"[Package]\"\n5\nField Unit\n\"[Field]\"\n6\nDevice\n\"[Device]\"\n7\nEvent\n\"[Event]\"\n8\nControl Method\n\"[Control Method]\"\n9\nMutex\n\"[Mutex]\"\n10\nOperation Region\n\"[Operation Region]\"\n11\nPower Resource\n\"[Power Resource]\"\n12\nProcessor\n\"[Processor]\"\n13\nThermal Zone\n\"[Thermal Zone]\"\n14\nBuffer Field\n\"[Buffer Field]\"\n15\nDDB Handle\n\"[DDB Handle]\"\n16\nDebug Object\n\"[Debug Object]\"", - "example": "Device (DEVX) {}\nName (PKGX, Package () {1,2,3,\"Battery1\"})\nMethod (MTHX, 2)\n{\n Concatenate (\"My Object: \", DEVX, Debug) // MyObject: Device\n Printf (\"PKGX %o contains %o elements\\n\", PKGX, SizeOf (PKGX))\n Printf (\"Arg0: %o\\n\", Arg0)\n}" - }, - { - "title": "ConcatenateResTemplate (Concatenate Resource Templates)", - "syntax": "ConcatenateResTemplate (Source1, Source2, Result) => Buffer", - "arguments": "Source1 and Source2 are evaluated as Resource Template buffers.", - "description": "The resource descriptors from Source2 are appended to the resource descriptors from Source1. Then a new end tag and checksum are appended and the result is stored in Result, if specified. If either Source1 or Source2 is exactly 1 byte in length, a run-time error occurs. An empty buffer is treated as a resource template with only an end tag.", - "example": "" - }, - { - "title": "CondRefOf (Create Object Reference Conditionally)", - "syntax": "CondRefOf (Source, Result) => Boolean", - "arguments": "Attempts to create a reference to the Source object. The Source of this operation can be any object type (for example, data package, device object, and so on), and the result data is optionally stored into Result.", - "description": "On success, the Destination object is set to refer to Source and the execution result of this operation is the value True. On failure, Destination is unchanged and the execution result of this operation is the value False. This can be used to reference items in the namespace that may appear dynamically (for example, from a dynamically loaded definition block).\nCondRefOf is equivalent to RefOf except that if the Source object does not exist, it is fatal for RefOf but not for CondRefOf.", - "example": "" - }, - { - "title": "Connection (Declare Field Connection Attributes)", - "syntax": "Connection (ConnectionResourceObj)", - "arguments": "ConnectionResourceObj is a GPIO or Serial Bus Connection Descriptor depending on the Operation Region type, or a named object containing the Descriptor\nSee Section 6.4.3.8.2, \"Connection Resource Descriptors\" and Section \"Field (Declare Field Objects)\" for more information.", - "description": "The Connection macro declares the connection attributes for subsequent fields defined within the Field declaration.", - "example": "OperationRegion(TOP1, GenericSerialBus, 0x00, 0x100)// GenericSerialBus device at command value offset zero\nName (I2C, ResourceTemplate(){\n I2CSerialBusV2(0x5a,,100000,, \"\\_SB.I2C\",,,,,RawDataBuffer(){1,6}) })\nField(TOP1, BufferAcc, NoLock, Preserve)\n{\n Connection(I2C) // Specify connection resource information\n AccessAs(BufferAcc, AttribWord) // Use the GenericSerialBus\n // Read/Write Word protocol FLD0, 8, // Virtual register at command value 0.\n FLD1, 8, // Virtual register at command value 1.\n \nField(TOP1, BufferAcc, NoLock, Preserve)\n{\n Connection(I2CSerialBusV2(0x5b,,100000,, \"\\_SB.I2C\",,,,,RawDataBuffer(){3,9})) AccessAs(BufferAcc, AttribBytes (16))\n FLD2, 8 // Virtual register at command value 0.\n}\n // Create the GenericSerialBus data buffer\nName(BUFF, Buffer(34){}) // Create GenericSerialBus data buffer as BUFF\nCreateByteField(BUFF, 0x00, STAT) // STAT = Status (Byte)\nCreateWordField(BUFF, 0x02, DATA) // DATA = Data (Word)" - }, - { - "title": "Continue (Continue Innermost Enclosing While)", - "syntax": "Continue", - "arguments": "", - "description": "Continue causes execution to continue at the start of the innermost enclosing While scope, in the currently executing Control Method, at the point where the condition is evaluated. If there is no enclosing While within the current Method, a fatal error is generated.", - "example": "" - }, - { - "title": "CopyObject (Copy and Store Object)", - "syntax": "CopyObject (Source, Destination) => DataRefObject", - "arguments": "Converts the contents of the Source to a DataRefObject using the conversion rules in 18.2.5 and then copies the results without conversion to the object referred to by Destination.", - "description": "If Destination is already an initialized object of type DataRefObject, the original contents of Destination are discarded and replaced with Source. Otherwise, a fatal error is generated.\nNote: (Compatibility Note) The CopyObject operator was first introduced new in ACPI 2.0.", - "example": "" - }, - { - "title": "CreateBitField (Create 1-Bit Buffer Field)", - "syntax": "CreateBitField (SourceBuffer, BitIndex, BitFieldName)", - "arguments": "SourceBuffer is evaluated as a buffer. BitIndex is evaluated as an integer. BitFieldName is a NameString.", - "description": "A new buffer field object named BitFieldName is created for the bit of SourceBuffer at the bit index of BitIndex. The bit-defined field within SourceBuffer must exist.BitFieldName is created for the bit of SourceBuffer at the bit index of BitIndex. The bit-defined field within SourceBuffer must exist.", - "example": "" - }, - { - "title": "CreateByteField (Create 8-Bit Buffer Field)", - "syntax": "CreateByteField (SourceBuffer, ByteIndex, ByteFieldName)", - "arguments": "SourceBuffer is evaluated as a buffer. ByteIndex is evaluated as an integer. ByteFieldName is a NameString.", - "description": "A new buffer field object named ByteFieldName is created for the byte of SourceBuffer at the byte index of ByteIndex. The byte-defined field within SourceBuffer must exist.", - "example": "" - }, - { - "title": "CreateDWordField (Create 32-Bit Buffer Field)", - "syntax": "CreateDWordField (SourceBuffer, ByteIndex, DWordFieldName)", - "arguments": "SourceBuffer is evaluated as a buffer. ByteIndex is evaluated as an integer. DWordFieldName is a NameString.", - "description": "A new buffer field object named DWordFieldName is created for the DWord of SourceBuffer at the byte index of ByteIndex. The DWord-defined field within SourceBuffer must exist.", - "example": "" - }, - { - "title": "CreateField (Create Arbitrary Length Buffer Field)", - "syntax": "CreateField (SourceBuffer, BitIndex, NumBits, FieldName)", - "arguments": "SourceBuffer is evaluated as a buffer. BitIndex and NumBits are evaluated as integers. FieldName is a NameString.", - "description": "A new buffer field object named FieldName is created for the bits of SourceBuffer at BitIndex for NumBits. The entire bit range of the defined field within SourceBuffer must exist. If NumBits evaluates to zero, a fatal exception is generated.", - "example": "" - }, - { - "title": "CreateQWordField (Create 64-Bit Buffer Field)", - "syntax": "CreateQWordField (SourceBuffer, ByteIndex, QWordFieldName)", - "arguments": "SourceBuffer is evaluated as a buffer. ByteIndex is evaluated as an integer. QWordFieldName is a NameString.", - "description": "A new buffer field object named QWordFieldName is created for the QWord of SourceBuffer at the byte index of ByteIndex. The QWord-defined field within SourceBuffer must exist.", - "example": "" - }, - { - "title": "CreateWordField (Create 16-Bit Buffer Field)", - "syntax": "CreateWordField (SourceBuffer, ByteIndex, WordFieldName)", - "arguments": "SourceBuffer is evaluated as a buffer. ByteIndex is evaluated as an integer. WordFieldName is a NameString.", - "description": "A new bufferfield object named WordFieldName is created for the word of SourceBuffer at the byte index of ByteIndex. The word-defined field within SourceBuffer must exist.", - "example": "" - }, - { - "title": "DataTableRegion (Create Data Table Operation Region)", - "syntax": "DataTableRegion (RegionName, SignatureString, OemIDString, OemTableIDString)", - "arguments": "Creates a new region named RegionName. SignatureString, OemIDString and OemTableIDString are evaluated as strings.", - "description": "A Data Table Region is a special Operation Region whose RegionSpace is SystemMemory. Any table referenced by a Data Table Region must be in memory marked by AddressRangeReserved or AddressRangeNVS.\nThe memory referred to by the Data Table Region is the memory that is occupied by the table referenced in XSDT that is identified by SignatureString, OemIDString and OemTableIDString. Any Field object can reference RegionName\nThe base address of a Data Table region is the address of the first byte of the header of the table identified by SignatureString, OemIDString and OemTableIDString. The length of the region is the length of the table.", - "example": "" - }, - { - "title": "Debug (Debugger Output)", - "syntax": "Debug", - "arguments": "", - "description": "The debug data object is a virtual data object. Writes to this object provide debugging information. On at least debug versions of the interpreter, any writes into this object are appropriately displayed on the system\u2019s native kernel debugger. All writes to the debug object are otherwise benign. If the system is in use without a kernel debugger, then writes to the debug object are ignored. The following table relates the ASL term types that can be written to the Debug object to the format of the information on the kernel debugger display.\nTable 19-429 Debug Object Display Formats\nASL Term Type\nDisplay Format\nNumeric data object\nAll digits displayed in hexadecimal format.\nString data object\nString is displayed.\nObject reference\nInformation about the object is displayed (for example, object type and object name), but the object is not evaluated.\nThe Debug object is a write-only object; attempting to read from the debug object is not supported.", - "example": "" - }, - { - "title": "Decrement (Integer Decrement)", - "syntax": "Decrement (Minuend) => Integer\nMinuend-- => Integer", - "arguments": "Minuend is evaluated as an Integer.", - "description": "This operation decrements the Minuend by one and the result is stored back to Minuend. Equivalent to Subtract (Minuend, 1, Minuend). Underflow conditions are ignored and the result is Ones.", - "example": "" - }, - { - "title": "Default (Default Execution Path in Switch)", - "syntax": "Default {TermList}", - "arguments": "TermList is a sequence of executable ASL expressions.", - "description": "Within the body of a Switch (page 1040) statement, the statements specified by TermList will be executed if no Case (page 948) statement value matches the Switch statement value. If Default is omitted and no Case match is found, none of the statements in the Switch body are executed. There can be at most one Default statement in the immediate scope of the parent Switch statement. The Default statement can appear anywhere in the body of the Switch statement.", - "example": "" - }, - { - "title": "DefinitionBlock (Declare Definition Block)", - "syntax": "DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision, OEMID, TableID, OEMRevision) {TermList}", - "arguments": "AMLFileName is a string that specifies the desired name of the translated output AML file. If the\nAMLFileName is a NULL (zero length) string, the ASL compiler will automatically create the filename (typically generated from the input filename/pathname).TableSignature is a string that contains the 4character ACPI signature. ComplianceRevision is an 8-bit value. OEMID is a 6-character string, TableId is an 8-character string, and OEMRevision is a 32-bit value. TermList is a sequence of executable ASL expressions.\nIf multiple DefinitionBlocks are defined in the same ASL file, the first DefinitionBlock defines the output AMLFileName as per the rule above.", - "description": "The DefinitionBlock term specifies the unit of data and/or AML code that the OS will load as part of the Differentiated Definition Block or as part of an additional Definition Block.\nThis unit of data and/or AML code describes either the base system or some large extension (such as a docking station). The entire DefinitionBlock will be loaded and compiled by the OS as a single unit.\nSystem software loads a definition block by referencing the objects in the TermList package in order. The object list is encoded as TermList, so that rather than describing a static object list, it is possible to describe a dynamic object list according to the system settings. See \"Section 5.4.2, Definition Block Loading.\"\nNote: For compatibility with ACPI versions before ACPI 2.0, the bit width of Integer objects is dependent on the ComplianceRevision of the DSDT. If the ComplianceRevision is less than 2, all integers are restricted to 32 bits. Otherwise, full 64-bit integers are used. The version of the DSDT sets the global integer width for all integers, including integers in SSDTs.", - "example": "" - }, - { - "title": "DerefOf (Dereference an Object Reference)", - "syntax": "DerefOf (Source) => Object", - "arguments": "Returns the object referred by the Source object reference.", - "description": "If the Source evaluates to an object reference, the actual contents of the object referred to are returned. If the Source evaluates to a string, the string is evaluated as an ASL name (relative to the current scope) and the contents of that object are returned. If the object specified by Source does not exist then a fatal error is generated. If the object specified is a reference generated by the Index() operator and refers to an uninitialized package element, then a fatal error is generated.\nNote: (Compatibility Note) The use of a String with DerefOf was first introduced in ACPI 2.0.", - "example": "" - }, - { - "title": "Device (Declare Device Package)", - "syntax": "Device (DeviceName) {TermList}", - "arguments": "Creates a Device object of name DeviceName, which represents a processor, a bus or a device, or any other similar hardware. Device opens a name scope.", - "description": "A Device Package is one of the basic ways the Differentiated Definition Block describes the hardware devices in the system to the operating software. Each Device Package is defined somewhere in the hierarchical namespace corresponding to that device\u2019s location in the system. Within the namespace of the device are other names that provide information and control of the device, along with any subdevices that in turn describe sub-devices, and so on.\nFor any device, the platform runtime firmware provides only information that is added to the device in a non-hardware standard manner. This type of value-added function is expressible in the ACPI Definition Block such that operating software can use the function.\nThe platform runtime firmware supplies Device Objects only for devices that are obtaining some systemadded function outside the device\u2019s normal capabilities and for any Device Object required to fill in the tree for such a device. For example, if the system includes a PCI device (integrated or otherwise) with no additional functions such as power management, the platform runtime firmware would not report such a device; however, if the system included an integrated ISA device below the integrated PCI device (device is an IS bridge), then the system would include a Device Package for the ISA device with the minimum feature being added being the ISA device\u2019s ID and configuration information and the parent PCI device, because it is required to get the ISA Device Package placement in the namespace correct.\nThe device object list is encoded as TermList, so that rather than describing a static device object list, it is possible to describe a dynamic device object list according to the system settings. See \"Section 5.4.2, Definition Block Loading.\"", - "example": "The following block of ASL sample code shows a nested use of Device objects to describe an IDE controller connected to the root PCI bus.\n Device (IDE0) { // primary controller\n Name (_ADR, 0) // put PCI Address (device/function) here\n // define region for IDE mode register\n OperationRegion (PCIC, PCI_Config, 0x50, 0x10)\n Field (PCIC, AnyAcc, NoLock, Preserve) {\n \u2026\n }\n Device (PRIM) { // Primary adapter\n Name (_ADR, 0) // Primary adapter = 0\n \u2026\n Method (_STM, 2) {\n \u2026\n }\n Method (_GTM) {\n \u2026\n }\n Device (MSTR) { // master channel\n Name (_ADR, 0)\n Name (_PR0, Package () {0, PIDE})\n Name (_GTF) {\n \u2026\n }\n }\n Device (SLAV) {\n Name (_ADR, 1)\n Name (_PR0, Package () {0, PIDE})\n Name (_GTF) {\n \u2026\n }\n }\n }\n }" - }, - { - "title": "Divide (Integer Divide)", - "syntax": "Divide (Dividend, Divisor, Remainder, Result) => Integer\nResult = Dividend / Divisor => Integer\nResult /= Divisor => Integer", - "arguments": "Dividend and Divisor are evaluated as Integers.", - "description": "Dividend is divided by Divisor, then the resulting remainder is optionally stored into Remainder and the resulting quotient is optionally stored into Result. Divide-by-zero exceptions are fatal.\nThe function return value is the Result (quotient).", - "example": "" - }, - { - "title": "DMA (DMA Resource Descriptor Macro)", - "syntax": "DMA (DmaType, IsBusMaster, DmaTransferSize, DescriptorName) {DmaChannelList} => Buffer Arguments\nDmaType specifies the type of DMA cycle: ISA compatible (Compatibility), EISA Type A (TypeA), EISA Type B (TypeB) or EISA Type F (TypeF). The 2-bit field DescriptorName._TYP is automatically created to refer to this portion of the resource descriptor, where \u20180\u2019 is Compatibility, \u20181\u2019 is TypeA, \u20182\u2019 is TypeB and \u20183\u2019 is TypeF.\nIsBusMaster specifies whether this device can generate DMA bus master cycles (BusMaster) or not (NotBusMaster). If nothing is specified, then BusMaster is assumed. The 1-bit field DescriptorName._BM is automatically created to refer to this portion of the resource descriptor, where \u20180\u2019 is NotBusMaster and \u20181\u2019 is BusMaster.\nDmaTransferSize specifies the size of DMA cycles the device is capable of generating: 8-bit (Transfer8), 16-bit (Transfer16) or both 8 and 16-bit (Transfer8_16). The 2-bit field DescriptorName._SIZ is automatically created to refer to this portion of the resource descriptor, where \u20180\u2019 is Transfer8, \u20181\u2019 is Transfer8_16 and \u20182\u2019 is Transfer16.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nDmaChannelList is a comma-delimited list of integers in the range 0 through 7 that specify the DMA channels used by the device. There may be no duplicates in the list.", - "arguments": "", - "description": "The DMA macro evaluates to a buffer which contains a DMA resource descriptor. The format of the DMA resource descriptor can be found in \u201cDMA Descriptor\u201d (page 420). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "DWordIO (DWord IO Resource Descriptor Macro)", - "syntax": "DWordIO (ResourceUsage, IsMinFixed, IsMaxFixed, Decode, ISARanges, AddressGranularity,\nAddressMinimum, AddressMaximum, AddressTranslation, RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName, TranslationType, TranslationDensity)", - "arguments": "ResourceUsage specifies whether the I/O range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nIsMinFixed specifies whether the minimum address of this I/O range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName._MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this I/O range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field DescriptorName._MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nDecode specifies whether or not the device decodes the I/O range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName._DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nISARanges specifies whether the I/O ranges specifies are limited to valid ISA I/O ranges (ISAOnly), valid non-ISA I/O ranges (NonISAOnly) or encompass the whole range without limitation (EntireRange). The 2bit field DescriptorName._RNG is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is NonISAOnly, \u20182\u2019 is ISAOnly and \u20180\u2019 is EntireRange.\nAddressGranularity evaluates to a 32-bit integer that specifies the power-of-two boundary (- 1) on which the I/O range must be aligned. The 32-bit field DescriptorName._GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 32-bit integer that specifies the lowest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 32-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 32-bit integer that specifies the highest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 32-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 32-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 32-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 32-bit integer that specifies the total number of bytes decoded in the I/O range. The 32-bit field DescriptorName._LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this I/O range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a value of zero is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nTranslationType is an optional argument that specifies whether the resource type on the secondary side of the bus is different (TypeTranslation) from that on the primary side of the bus or the same\n(TypeStatic). If TypeTranslation is specified, then the primary side of the bus is Memory. If TypeStatic is specified, then the primary side of the bus is I/O. If nothing is specified, then TypeStatic is assumed. The 1-bit field DescriptorName._TTP is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is TypeTranslation and \u20180\u2019 is TypeStatic. See _TTP (page 443) for more information\nTranslationDensity is an optional argument that specifies whether or not the translation from the primary to secondary bus is sparse (SparseTranslation) or dense (DenseTranslation). It is only used when TranslationType is TypeTranslation. If nothing is specified, then DenseTranslation is assumed. The 1-bit field DescriptorName._TRS is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SparseTranslation and \u20180\u2019 is DenseTranslation. See _TRS (page 444) for more information.", - "description": "The DWordIO macro evaluates to a buffer which contains a 32-bit I/O range resource descriptor. The format of the 32-bit I/O range resource descriptor can be found in \u201cDWord Address Space Descriptor \u201d (page 435). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "DWordMemory (DWord Memory Resource Descriptor Macro)", - "syntax": "DWordMemory (ResourceUsage, Decode, IsMinFixed, IsMaxFixed, Cacheable, ReadAndWrite,\nAddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, RangeLength,\nResourceSourceIndex, ResourceSource, DescriptorName, MemoryRangeType, TranslationType)", - "arguments": "ResourceUsage specifies whether the Memory range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nDecode specifies whether or not the device decodes the Memory range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName._DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nIsMinFixed specifies whether the minimum address of this Memory range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName._MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this Memory range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName._MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nCacheable specifies whether or not the memory region is cacheable (Cacheable), cacheable and writecombining (WriteCombining), cacheable and prefetchable (Prefetchable) or uncacheable\n(NonCacheable). If nothing is specified, then NonCacheable is assumed. The 2-bit field\nDescriptorName._MEM is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Cacheable, \u20182\u2019 is WriteCombining, \u20183\u2019 is Prefetchable and \u20180\u2019 is NonCacheable.\nReadAndWrite specifies whether or not the memory region is read-only (ReadOnly) or read/write\n(ReadWrite). If nothing is specified, then ReadWrite is assumed. The 1-bit field DescriptorName._RW is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is ReadWrite and \u20180\u2019 is ReadOnly.\nAddressGranularity evaluates to a 32-bit integer that specifies the power-of-two boundary (- 1) on which the Memory range must be aligned. The 32-bit field DescriptorName._GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 32-bit integer that specifies the lowest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 32-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 32-bit integer that specifies the highest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 32-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 32-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 32-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 32-bit integer that specifies the total number of bytes decoded in the Memory range. The 32-bit field DescriptorName._LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this Memory range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nMemoryRangeType is an optional argument that specifies the memory usage. The memory can be marked as normal (AddressRangeMemory), used as ACPI NVS space (AddressRangeNVS), used as ACPI reclaimable space (AddressRangeACPI) or as system reserved (AddressRangeReserved). If nothing is specified, then AddressRangeMemory is assumed. The 2-bit field DescriptorName._MTP is automatically created in order to refer to this portion of the resource descriptor, where \u20180\u2019 is AddressRangeMemory, \u20181\u2019 is AddressRangeReserved, \u20182\u2019 is AddressRangeACPI and \u20183\u2019 is AddressRangeNVS.\nTranslationType is an optional argument that specifies whether the resource type on the secondary side of the bus is different (TypeTranslation) from that on the primary side of the bus or the same (TypeStatic). If TypeTranslation is specified, then the primary side of the bus is I/O. If TypeStatic is specified, then the primary side of the bus is Memory. If nothing is specified, then TypeStatic is assumed. The 1-bit field DescriptorName._TTP is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is TypeTranslation and \u20180\u2019 is TypeStatic. See _TTP (page 443) for more information.", - "description": "The DWordMemory macro evaluates to a buffer which contains a 32-bit memory resource descriptor. The format of the 32-bit memory resource descriptor can be found in \u201cDWord Address Space Descriptor \u201d (page 435). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "DWordSpace (DWord Space Resource Descriptor Macro)", - "syntax": "DWordSpace (ResourceType, ResourceUsage, Decode, IsMinFixed, IsMaxFixed, TypeSpecificFlags,\nAddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName)", - "arguments": "ResourceType evaluates to an 8-bit integer that specifies the type of this resource. Acceptable values are 0xC0 through 0xFF.\nResourceUsage specifies whether the Memory range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nDecode specifies whether or not the device decodes the Memory range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName._DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nIsMinFixed specifies whether the minimum address of this Memory range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName._MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this Memory range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName._MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nTypeSpecificFlags evaluates to an 8-bit integer. The flags are specific to the ResourceType.\nAddressGranularity evaluates to a 32-bit integer that specifies the power-of-two boundary (- 1) on which the Memory range must be aligned. The 32-bit field DescriptorName._GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 32-bit integer that specifies the lowest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 32-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 32-bit integer that specifies the highest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 32-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 32-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 32-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 32-bit integer that specifies the total number of bytes decoded in the Memory range. The 32-bit field DescriptorName._LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this Memory range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The DWordSpace macro evaluates to a buffer which contains a 32-bit Address Space resource descriptor. The format of the 32-bit Address Space resource descriptor can be found in \u201cDWord Address Space Descriptor \u201d (page 435). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "EISAID (EISA ID String To Integer Conversion Macro)", - "syntax": "EISAID (EisaIdString) => DWordConst", - "arguments": "The EisaIdString must be a String object of the form \u201cUUUNNNN\u201d, where \u201cU\u201d is an uppercase letter and \u201cN\u201d is a hexadecimal digit. No asterisks or other characters are allowed in the string.", - "description": "Converts EisaIdString, a 7-character text string argument, into its corresponding 4-byte numeric EISA ID encoding. It can be used when declaring IDs for devices that have EISA IDs.", - "example": " EISAID (\u201cPNP0C09\u201d) // This is a valid invocation of the macro." - }, - { - "title": "Else (Alternate Execution)", - "syntax": "Else {TermList}", - "arguments": "TermList is a sequence of executable ASL statements.", - "description": "If Predicate evaluates to 0 in an If statement, then control is transferred to the Else portion, which can consist of zero or more ElseIf statements followed by zero or one Else statements. If the Predicate of any ElseIf statement evaluates to non-zero, the statements in its term list are executed and then control is transferred past the end of the final Else term. If no Predicate evaluates to non-zero, then the statements in the Else term list are executed.", - "example": "The following example checks Local0 to be zero or non-zero. On non-zero, CNT is incremented; otherwise, CNT is decremented.\nIf (LGreater (Local0, 5)\n{\n Increment (CNT)\n} Else If (Local0) {\n Add (CNT, 5, CNT)\n}\nElse\n{\n Decrement (CNT)\n}" - }, - { - "title": "ElseIf (Alternate/Conditional Execution)", - "syntax": "ElseIf (Predicate) {TermList}", - "arguments": "Predicate is evaluated as an Integer.", - "description": "If the Predicate of any ElseIf statement evaluates to non-zero, the statements in its term list are executed and then control is transferred past the end of the final Else. If no Predicate evaluates to non-zero, then the statements in the Else term list are executed.\nNote: (Compatibility Note) The ElseIf operator was first introduced in ACPI 2.0, but is backward compatible with the ACPI 1.0 specification. An ACPI 2.0 and later ASL compiler must synthesize ElseIf from the If. and Else opcodes available in 1.0. For example:\nIf (predicate1)\n{\n \u2026statements1\u2026\n}\nElseIf (predicate2)\n{\n \u2026statements2\u2026\n}\nElse\n{\n \u2026statements3\u2026\n}\nis translated to the following:\nIf (predicate1)\n{\n \u2026statements1\u2026\n}\nElse\n{\n If (predicate2)\n {\n \u2026statements2\u2026\n }\n Else\n {\n \u2026statements3\u2026\n } }", - "example": "" - }, - { - "title": "EndDependentFn (End Dependent Function Resource Descriptor Macro)", - "syntax": "EndDependentFn () => Buffer", - "arguments": "", - "description": "The EndDependentFn macro generates an end-of-dependent-function resource descriptor buffer inside of an ResourceTemplate (page 1033). It must be matched with a StartDependentFn (page 1038) or StartDependentFnNoPri (page 1038) macro.", - "example": "" - }, - { - "title": "Event (Declare Event Synchronization Object)", - "syntax": "Event (EventName)", - "arguments": "Creates an event synchronization object named EventName.", - "description": "For more information about the uses of an event synchronization object, see the ASL definitions for the Wait, Signal, and Reset function operators.", - "example": "" - }, - { - "title": "ExtendedIO (Extended IO Resource Descriptor Macro)", - "syntax": "ExtendedIO (ResourceUsage, IsMinFixed, IsMaxFixed, Decode, ISARanges, AddressGranularity,\nAddressMinimum, AddressMaximum, AddressTranslation, RangeLength, TypeSpecificAttributes, DescriptorName, TranslationType, TranslationDensity)", - "arguments": "ResourceUsage specifies whether the Memory range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nIsMinFixed specifies whether the minimum address of this I/O range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName._MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this I/O range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName._MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nDecode specifies whether or not the device decodes the I/O range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName._DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nISARanges specifies whether the I/O ranges specifies are limited to valid ISA I/O ranges (ISAOnly), valid non-ISA I/O ranges (NonISAOnly) or encompass the whole range without limitation (EntireRange). The 2bit field DescriptorName._RNG is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is NonISAOnly, \u20182\u2019 is ISAOnly and \u20180\u2019 is EntireRange.\nAddressGranularity evaluates to a 64-bit integer that specifies the power-of-two boundary (- 1) on which the I/O range must be aligned. The 64-bit field DescriptorName._GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 64-bit integer that specifies the lowest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 64-bit integer that specifies the highest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 64-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 64-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 64-bit integer that specifies the total number of bytes decoded in the I/O range. The 64-bit field DescriptorName._LEN is automatically created to refer to this portion of the resource descriptor.\nTypeSpecificAttributes is an optional argument that specifies attributes specific to this resource type. See Section 6.4.3.5.4.1,\u201dType Specific Attributes\u201d.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operatorsDescription\nThe ExtendedIO macro evaluates to a buffer which contains a 64-bit I/O resource descriptor, which describes a range of I/O addresses. The format of the 64-bit I/O resource descriptor can be found in \u201cExtended Address Space Descriptor\u201d (page 425). The macro is designed to be used inside of a ResourceTemplate (page 1033).\nTranslationType is an optional argument that specifies whether the resource type on the secondary side of the bus is different (TypeTranslation) from that on the primary side of the bus or the same\n(TypeStatic). If TypeTranslation is specified, then the primary side of the bus is Memory. If TypeStatic is specified, then the primary side of the bus is I/O. If nothing is specified, then TypeStatic is assumed. The 1-bit field DescriptorName. _TTP is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is TypeTranslation and \u20180\u2019 is TypeStatic. See _TTP (page 443) for more information\nTranslationDensity is an optional argument that specifies whether or not the translation from the primary to secondary bus is sparse (SparseTranslation) or dense (DenseTranslation). It is only used when TranslationType is TypeTranslation. If nothing is specified, then DenseTranslation is assumed. The 1-bit field DescriptorName._TRS is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SparseTranslation and \u20180\u2019 is DenseTranslation. See _TRS (page 444) for more information.", - "description": "", - "example": "" - }, - { - "title": "ExtendedMemory (Extended Memory Resource Descriptor Macro)", - "syntax": "ExtendedMemory (ResourceUsage, Decode, IsMinFixed, IsMaxFixed, Cacheable, ReadAndWrite,\nAddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, RangeLength, TypeSpecificAttributes, DescriptorName, MemoryRangeType, TranslationType)", - "arguments": "ResourceUsage specifies whether the Memory range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nDecode specifies whether or not the device decodes the Memory range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName._DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nIsMinFixed specifies whether the minimum address of this Memory range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field DescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this Memory range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nCacheable specifies whether or not the memory region is cacheable (Cacheable), cacheable and writecombining (WriteCombining), cacheable and prefetchable (Prefetchable) or uncacheable\n(NonCacheable). If nothing is specified, then NonCacheable is assumed. The 2-bit field\nDescriptorName._MEM is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Cacheable, \u20182\u2019 is WriteCombining, \u20183\u2019 is Prefetchable and \u20180\u2019 is NonCacheable.\nReadAndWrite specifies whether or not the memory region is read-only (ReadOnly) or read/write (ReadWrite). If nothing is specified, then ReadWrite is assumed. The 1-bit field DescriptorName._RW is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is ReadWrite and \u20180\u2019 is ReadOnly.\nAddressGranularity evaluates to a 64-bit integer that specifies the power-of-two boundary (- 1) on which the Memory range must be aligned. The 64-bit field DescriptorName._GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 64-bit integer that specifies the lowest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName ._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 64-bit integer that specifies the highest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName ._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 64-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 64-bit field DescriptorName. _TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 64-bit integer that specifies the total number of bytes decoded in the Memory range. The 64-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nTypeSpecificAttributes is an optional argument that specifies attributes specific to this resource type. See Section 6.4.3.5.4.1,\u201dType Specific Attributes\u201d.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nMemoryRangeType is an optional argument that specifies the memory usage. The memory can be marked as normal (AddressRangeMemory), used as ACPI NVS space (AddressRangeNVS), used as ACPI reclaimable space (AddressRangeACPI) or as system reserved (AddressRangeReserved). If nothing is specified, then AddressRangeMemory is assumed. The 2-bit field DescriptorName. _MTP is automatically created in order to refer to this portion of the resource descriptor, where \u20180\u2019 is AddressRangeMemory, \u20181\u2019 is AddressRangeReserved, \u20182\u2019 is AddressRangeACPI and \u20183\u2019 is AddressRangeNVS.\nTranslationType is an optional argument that specifies whether the resource type on the secondary side of the bus is different (TypeTranslation) from that on the primary side of the bus or the same (TypeStatic). If TypeTranslation is specified, then the primary side of the bus is I/O. If TypeStatic is specified, then the primary side of the bus is Memory. If nothing is specified, then TypeStatic is assumed. The 1-bit field DescriptorName. _TTP is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is TypeTranslation and \u20180\u2019 is TypeStatic. See _TTP (page 443) for more information.", - "description": "The ExtendedMemory macro evaluates to a buffer which contains a 64-bit memory resource descriptor, which describes a range of memory addresses. The format of the 64-bit memory resource descriptor can be found in \u201cExtended Address Space Descriptor\u201d (page 439). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "ExtendedSpace (Extended Address Space Resource Descriptor Macro)", - "syntax": "ExtendedSpace (ResourceType, ResourceUsage, Decode, IsMinFixed, IsMaxFixed, TypeSpecificFlags,\nAddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, RangeLength, TypeSpecificAttributes, DescriptorName)", - "arguments": "ResourceType evaluates to an 8-bit integer that specifies the type of this resource. Acceptable values are 0xC0 through 0xFF.\nResourceUsage specifies whether the Memory range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nDecode specifies whether or not the device decodes the Memory range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nIsMinFixed specifies whether the minimum address of this Memory range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this Memory range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nTypeSpecificFlags evaluates to an 8-bit integer. The flags are specific to the ResourceType.\nAddressGranularity evaluates to a 64-bit integer that specifies the power-of-two boundary (- 1) on which the Memory range must be aligned. The 64-bit field DescriptorName. _GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 64-bit integer that specifies the lowest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 64-bit integer that specifies the highest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 64-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 64-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 64-bit integer that specifies the total number of bytes decoded in the Memory range. The 64-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nTypeSpecificAttributes is an optional argument that specifies attributes specific to this resource type. See Section 6.4.3.5.4.1,\u201dType Specific Attributes\u201d.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The ExtendedSpace macro evaluates to a buffer which contains a 64-bit Address Space resource descriptor, which describes a range of addresses. The format of the 64-bit AddressSpace descriptor can be found in \u201cExtended Address Space Descriptor\u201d (page 439). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "External (Declare External Objects)", - "syntax": "External (ObjectName, ObjectType, ReturnType, ParameterTypes)", - "arguments": "ObjectName is a NameString.\nObjectType is an optional ObjectTypeKeyword (e.g. IntObj, PkgObj, etc.). If not specified, \u201cUnknownObj\u201d type is assumed.\nReturnType is optional. If the specified ObjectType is MethodObj, then this specifies the type or types of object returned by the method. If the method does not return an object, then nothing is specified or UnknownObj is specified. To specify a single return type, simply use the ObjectTypeKeyword. To specify multiple possible return types, enclose the comma-separated ObjectTypeKeywords with braces. For example: {IntObj, BuffObj}.\nParameterTypes is optional. If the specified ObjectType is MethodObj, this specifies both the number and type of the method parameters. It is a comma-separated, variable-length list of the expected object type or types for each of the method parameters, enclosed in braces. For each parameter, the parameter type consists of either an ObjectTypeKeyword or a comma-separated sub-list of ObjectTypeKeywords enclosed in braces. There can be no more than seven parameters in total.Description\nThe External directive informs the ASL compiler that the object is declared external to this table so that no errors will be generated for an undeclared object. The ASL compiler will create the external object at the specified place in the namespace (if a full path of the object is specified), or the object will be created at the current scope of the External term.\nFor external control methods, the ASL compiler can emit an External AML opcode that contains the name of the method and the number of required arguments. This information may be used by AML disassemblers to properly disassemble the AML to the correct ASL code.\nExternal is especially useful for use in secondary SSDTs, when the required scopes and objects are declared in the main DSDT.", - "description": "", - "example": "This example shows the use of External in conjunction with Scope within an SSDT:\nDefinitionBlock (\"ssdt.aml\", \"SSDT\", 2, \"X\", \"Y\", 0x00000001)\n{\n External (\\_SB.PCI0, DeviceObj)\n Scope (\\_SB.PCI0)\n { }\n}" - }, - { - "title": "Fatal (Fatal Error Check)", - "syntax": "Fatal (Type, Code, Arg)", - "arguments": "This operation is used to inform the OS that there has been an OEM-defined fatal error.", - "description": "In response, the OS must log the fatal event and perform a controlled OS shutdown in a timely fashion.", - "example": "" - }, - { - "title": "Field (Declare Field Objects)", - "syntax": "Field (RegionName, AccessType, LockRule, UpdateRule) {FieldUnitList}", - "arguments": "RegionName is evaluated as a Namestring that refers to the host operation region.\nAccessType is optional and defines the default access width of the field definition and is any one of the following: AnyAcc, ByteAcc, WordAcc, DWordAcc, or QWordAcc. In general, accesses within the parent object are performed naturally aligned. If desired, AccessType set to a value other than AnyAcc can be used to force minimum access width. Notice that the parent object must be able to accommodate the AccessType width. For example, an access type of WordAcc cannot read the last byte of an odd-length operation region. The exceptions to natural alignment are the access types used for a non-linear SMBus device. These will be discussed in detail below. Not all access types are meaningful for every type of operational region. If not specified, the default is AnyAcc.\nLockRule is optional and indicates whether the Global Lock is to be used when accessing this field and is one of the following: Lock or NoLock. If LockRule is set to Lock, accesses to modify the component data objects will acquire and release the Global Lock. If both types of locking occur, the Global Lock is acquired after the parent object Mutex. On Hardware-reduced ACPI platforms, Lock is not supported. If not specified, the default is NoLock.\nUpdateRule is optional and specifieas how the unmodified bits of a field are treated, and can be any one of the following: Preserve, WriteAsOnes, or WriteAsZeros. For example, if a field defines a component data object of 4 bits in the middle of a WordAcc region, when those 4 bits are modified the UpdateRule specifies how the other 12 bits are treated. If not specified, the default is Preserve.\nFieldUnitList is a variable-length list of individual field unit definitions, separated by commas. Each entry in the field unit list is one of the following:\nTable 19-430 Field Unit list entires\nFieldUnitName, BitLength\nOffset (ByteOffset)\nAccessAs (AccessType, AccessAttribute)\nConnection (ConnectionResourceObj)\nFieldUnitName is the ACPI name for the field unit (1 to 4 characters), and BitLength is the length of the field unit in bits. Offset is used to specify the byte offset of the next defined field unit. This can be used instead of defining the bit lengths that need to be skipped. AccessAs is used to define the access type and attributes for the remaining field units within the list. Connection is used to identify the connection resource of the field access. This is necessary for GenericSerialBus and GeneralPurposeIO operation region address spaces only.", - "description": "Declares a series of named data objects whose data values are fields within a larger object. The fields are parts of the object named by RegionName, but their names appear in the same scope as the Field term.\nFor example, the field operator allows a larger operation region that represents a hardware register to be broken down into individual bit fields that can then be accessed by the bit field names. Extracting and combining the component field from its parent is done automatically when the field is accessed.\nWhen reading from a FieldUnit, returned values are normalized (shifted and masked to the proper length.) The data type of an individual FieldUnit can be either a Buffer or an Integer, depending on the bit length of the FieldUnit. If the FieldUnit is smaller than or equal to the size of an Integer (in bits), it will be treated as an Integer. If the FieldUnit is larger than the size of an Integer, it will be treated as a Buffer. The size of an Integer is indicated by the DSDT header\u2019s Revision field. A revision less than 2 indicates that the size of an Integer is 32 bits. A value greater than or equal to 2 signifies that the size of an Integer is 64 bits. For more information about data types and FieldUnit type conversion rules, see Section 19.3.5.7, \u201cData Type Conversion Rules\u201d.\nAccessing the contents of a field data object provides access to the corresponding field within the parent object. If the parent object supports Mutex synchronization, accesses to modify the component data objects will acquire and release ownership of the parent object around the modification.\nThe following table relates region types declared with an OperationRegion term to the different access types supported for each region.\nTable 19-431 OperationRegion Address Spaces and Access Types\nAddress Space\nPermitted Access Type(s)\nSystemMemory\nByteAcc, WordAcc, DWordAcc, QWordAcc, or AnyAcc\nAll access allowed\nSystemIO\nByteAcc, WordAcc, DWordAcc, QWordAcc, or AnyAcc\nAll access allowed\nPCI_Config\nByteAcc, WordAcc, DWordAcc, QWordAcc, or AnyAcc\nAll access allowed\nEmbeddedControl\nByteAcc\nByte access only\nSMBus\nBufferAcc\nReads and writes to this operation region involve the use of a region specific data buffer.\n(See below.)\nSystemCMOS\nByteAcc\nByte access only\nPciBarTarget\nByteAcc, WordAcc, DWordAcc, QWordAcc, or AnyAcc\nAll access allowed\nIPMI\nBufferAcc\nReads and writes to this operation region involve the use of a region specific data buffer.\n(See below.)\nGeneralPurposeIO\nByteAcc\nByte access only\nGenericSerialBus\nBufferAcc\nReads and writes to this operation region involve the use of a region-specific data buffer.\n(See below.)\nPCC\nByteAcc\nReads and writes to this operation region are performed in units of bytes.\nThe named FieldUnit data objects are provided in the FieldList as a series of names and bit widths. Bits assigned no name (or NULL) are skipped. The ASL compiler supports the Offset (ByteOffset) macro within a FieldList to skip to the bit position of the supplied byte offset, and the AccessAs macro to change access within the field list.\nGenericSerialBus, SMBus and IPMI regions are inherently non-linear, where each offset within the respective address space represents a variable sized (0 to 32 bytes) field. Given this uniqueness, these operation regions include restrictions on their field definitions and require the use of a region-specific data buffer when initiating transactions. For more information on the SMBus data buffer format, see Section 13, \u201cACPI System Management Bus Interface Specification,\u201d. For more information on the IPMI data buffer format, see Section 5.5.2.4.4, \u201cDeclaring IPMI Operation Regions\". For more information on the Generic Serial Bus data buffer format, see Section 5.5.2.4.6 \"Declaring Generic Serial Bus Operation Regions.\"\nFor restrictions on the use of Fields with GeneralPurposeIO OpRegions, see Section 5.5.2.4.5, \"Declaring General PurposeIO Operation Regions\".", - "example": "OperationRegion (MIOC, PCI_Config, Zero, 0xFF)\nField (MIOC, AnyAcc, NoLock, Preserve)\n{\n Offset (0x58), \uf020\n HXGB, 32, \uf020\n HXGT, 32, \uf020\n GAPE, 8, \uf020\n MR0A, 4, \uf020\n MR0B, 4\n}" - }, - { - "title": "FindSetLeftBit (Find First Set Left Bit)", - "syntax": "FindSetLeftBit (Source, Result) => Integer", - "arguments": "Source is evaluated as an Integer.", - "description": "The one-based bit location of the first MSb (most significant set bit) is optionally stored into Result. The result of 0 means no bit was set, 1 means the left-most bit set is the first bit, 2 means the left-most bit set is the second bit, and so on.", - "example": "" - }, - { - "title": "FindSetRightBit (Find First Set Right Bit)", - "syntax": "FindSetRightBit (Source, Result) => Integer", - "arguments": "Source is evaluated as an Integer.", - "description": "The one-based bit location of the most LSb (least significant set bit) is optionally stored in Result. The result of 0 means no bit was set, 32 means the first bit set is the thirty-second bit, 31 means the first bit set is the thirty-first bit, and so on.", - "example": "" - }, - { - "title": "FixedDMA (DMA Resource Descriptor Macro)", - "syntax": "FixedDMA (DmaRequestLine, Channel, DmaTransferWidth, DescriptorName) => Buffer", - "arguments": "DmaRequestLine is a system-relative number uniquely identifying the request line statically assigned to the device.. The bit field name _DMA is automatically created to refer to this portion of the resource descriptor.\nChannel is a controller-relative number uniquely identifying the channel statically assigned to this DMARequestLine. Channels can be shared by reusing Channel numbers across descriptors. The bit field name _TYP is automatically created to refer to this portion of the resource descriptor.\nDmaTransferWidth is an optional argument specifying the width of data transfer for which the device is configured. Valid values are Width8Bit, Width16Bit, Width32Bit,Width64Bit, Width 128Bit or\nWidth256Bit. If not specified, Width32Bit is assumed. The bit field name _SIZ is automatically created to refer to this portion of the resource descriptor.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The FixedDMA macro evaluates to a buffer that contains a Fixed DMA Descriptor (Section 6.4.3).", - "example": "" - }, - { - "title": "FixedIO (Fixed IO Resource Descriptor Macro)", - "syntax": "FixedIO (AddressBase, RangeLength, DescriptorName) => Buffer", - "arguments": "AddressBase evaluates to a 16-bit integer. It describes the starting address of the fixed I/O range. The field DescriptorName. _BAS is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to an 8-bit integer. It describes the length of the fixed I/O range. The field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nDescriptorName evaluates to a name string which refers to the entire resource descriptor.", - "description": "The FixedIO macro evaluates to a buffer which contains a fixed I/O resource descriptor. The format of the fixed I/O resource descriptor can be found in \u201cFixed Location I/O Port Descriptor \u201d (page 423). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "For (Conditional Loop)", - "syntax": "For (Initialize, Predicate, Update) {TermList}", - "arguments": "Initialize. This optional expression is evaluated once before the loop is entered. If not specified, no initialization takes place.\nPredicate. The list of terms within the TermList are executed until the predicate evaluates to zero (FALSE). If this argument is not specified, the For macro is equivalent to While(1).\nUpdate. This optional expression is evaluated once per execution of the loop, after all other terms within the TermList have been executed.", - "description": "For is a macro that creates a loop by converting the input arguments to the equivalent ASL While loop.\nNote: Creation of a named object more than once in a given scope is not allowed. As such, unconditionally creating named objects within a For loop must be avoided. A fatal error will be generated on the second iteration of the loop, during the attempt to create the same named object a second time.", - "example": "The following example shows the use of the For macro to create a loop, followed by the equivalent While loop that is actually emitted by the ASL compiler:\n for (local0 = 0, local0 < 8, local0++)\n {\n }\n Local0 = 0\n While (Local0 < 8)\n {\n Local0++\n }" - }, - { - "title": "Fprintf (Create and Store formatted string)", - "syntax": "Fprintf (Destination, FormatString, FormatArgs) => String", - "arguments": "Fprintf is a macro that converts the evaluated FormatString into a series of string Concatenate operations, storing the result in Destination.\nFormatString is a string literal which may contain one or more uses of the format specifier, %o, to indicate locations in the string where an object may be inserted. %o is the only format specifier supported since the resulting object is a string and type conversion is handled automatically by Concatenate.\nFormatArgs is a comma separated list of Named Objects, Locals, or Args that can be evaluated to a string. Each argument is added to the FormatString using the Concatenate operation at the location specified by %o in order of appearance.", - "description": "Fprintf is a macro that converts the evaluated FormatString into a series of string Concatenate operations, storing the result in Destination", - "example": "The following ASL example uses Fprintf to write a formatted string of Arg0 and Arg1 to the Named Object STR1.\n Fprintf (STR1, \"%o: %o Successful\", Arg1, Arg0)\nThis Fprintf macro expression evaluates to the following ASL operation.\n Store (Concatenate (Concatenate (Concatenate (Concatenate\n (\"\", Arg1), \": \"), Arg0), \" Successful\"), STR1)" - }, - { - "title": "FromBCD (Convert BCD To Integer)", - "syntax": "FromBCD (BCDValue, Result) => Integer", - "arguments": "BCDValue is evaluated as an Integer in Binary Coded Decimal format.", - "description": "The FromBCD operation converts BCDValue to a numeric format, and optionally stores the numeric value into Result.", - "example": "" - }, - { - "title": "Function (Declare Control Method)", - "syntax": "Function (FunctionName, ReturnType, ParameterTypes) {TermList}", - "arguments": "ReturnType is optional and specifies the type(s) of the object(s) returned by the method. If the method does not return an object, then nothing is specified or UnknownObj is specified. To specify a single return type, simply use the ObjectTypeKeyword (e.g. IntObj, PkgObj, etc.). To specify multiple possible return types, enclose the comma-separated ObjectTypeKeywords with braces. For example: {IntObj, BuffObj}.\nParameterTypes is optional and specifies both the number and type of the method parameters. It is a comma-separated, variable-length list of the expected object type or types for each of the method parameters, enclosed in braces. For each parameter, the parameter type consists of either an\nObjectTypeKeyword or a comma-separated sub-list of ObjectTypeKeywords enclosed in braces. There can be no more than seven parameters in total.", - "description": "Function declares a named package containing a series of terms that collectively represent a control method. A control method is a procedure that can be invoked to perform computation. Function opens a name scope.\nSystem software executes a control method by executing the terms in the package in order. For more information on method execution, see Section 5.5.2, \u201cControl Method Execution.\u201d\nThe current namespace location used during name creation is adjusted to be the current location on the namespace tree. Any names created within this scope are \u201cbelow\u201d the name of this package. The current namespace location is assigned to the method package, and all namespace references that occur during control method execution for this package are relative to that location.\nFunctions are equivalent to a Method that specifies NotSerialized. As such, a function should not create any named objects, since a second thread that might re-enter the function will cause a fatal error if an attempt is made to create the same named object twice.\nNote: (Compatibility Note) New for ACPI 3.0", - "example": "The following block of ASL sample code shows the use of Function for defining a control method:\nFunction (EXAM, IntObj, {StrObj, {IntObj, StrObj}})\n{\n Name (Temp,\u201d\u201d)\n Store (Arg0, Temp) // could have used Arg1\n Return (SizeOf (Concatenate (Arg1, Temp)))\n}\nThis declaration is equivalent to:\nMethod (EXAM, 2, NotSerialized, 0, IntObj, {StrObj, {IntObj, StrObj}})\n{\n\u2026\n}" - }, - { - "title": "GpioInt (GPIO Interrupt Connection Resource Descriptor Macro)", - "syntax": "", - "arguments": "EdgeLevel can be either Edge or Level. The bit field name _MOD is automatically created to refer to this portion of the resource descriptor.\nActiveLevel can be one of ActiveHigh, ActiveLow or ActiveBoth. ActiveBoth can be specified only if EdgeLevel is Edge. The bit field name _POL is automatically created to refer to this portion of the resource descriptor.\nShared is an optional argument and can be one of Shared, Exclusive, SharedAndWake or\nExclusiveAndWake. If not specified, Exclusive is assumed. The \"Wake\" designation indicates that the interrupt is capable of waking the system from a low-power idle state or a system sleep state. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\nPinConfig can be one of PullDefault, PullUp, PullDown, PullNone or a vendor-supplied value in the range 128-255. The bit field name _PPI is automatically created to refer to this portion of the resource descriptor.\nDebounceTimeout is an optional argument specifying the debounce wait time, in hundredths of milliseconds. The bit field name _DBT is automatically created to refer to this portion of the resource descriptor.\nResourceSource is a string which uniquely identifies the GPIO controller referred to by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\nResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\nResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nVendorData is an optional argument that specifies a RawDataBuffer containing vendor-defined byte data to be decoded by the OS driver. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.\nPinList is a list of (zero-based) pin numbers on the ResourceSource that are described by this descriptor. For interrupt pin descriptors, only one pin is allowed. The bit field name _PIN is automatically created to refer to this portion of the resource descriptor.", - "description": "The GpioInt macro evaluates to a buffer that contains a GPIO Interrupt Connection resource descriptor.\nThe format of the GPIO Interrupt Connection resource descriptor can be found in \"GPIO Connection Descriptor\" (Section 6.4.3.8.1). The macro is designed to be used inside of a Resource Template (Section 19.3.3).", - "example": "" - }, - { - "title": "GpioIo (GPIO Connection IO Resource Descriptor Macro)", - "syntax": "", - "arguments": "Shared is an optional argument and can be either Shared or Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\nPinConfig can be one of PullDefault, PullUp, PullDown, PullNone or a vendor-supplied value in the range 128-255. The bit field name _PPI is automatically created to refer to this portion of the resource descriptor.\nDebounceTimeout is an optional argument specifying the hardware debounce wait time, in hundredths of milliseconds. The bit field name _DBT is automatically created to refer to this portion of the resource descriptor.\nDriveStrength is an optional argument specifying the output drive capability of the pin, in hundredths of milliamperes. The bit field name _DRS is automatically created to refer to this portion of the resource descriptor.\nIORestriction is an optional argument and can be IoRestrictionInputOnly, IoRestrictionOutputOnly, IoRestrictionNone, or IORestrictionNoneAndPreserve. IORestrictions limit the mode in which the pin can be accessed (Input or Output). They also ensure that the pin configuration is preserved during periods when the driver is unloaded or the resource has been disconnected by the driver. If not specified, IoRestrictionNone is assumed. The bit field name _IOR is automatically created to refer to this portion of the resource descriptor.\nResourceSource is a string which uniquely identifies the GPIO controller referred to by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\nResourceSourceIndex is an optional argument and is always 0 for this revision.\nResourceUsage is an optional argument and is always ResourceConsumer for this revision.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nVendorData is an optional argument that specifies a RawDataBuffer containing vendor-defined byte data to be decoded by the OS driver. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.\nPinList is a list of pin numbers on the ResourceSource that are described by this descriptor. The bit field name _PIN is automatically created to refer to this portion of the resource descriptor.", - "description": "The GpioIo macro evaluates to a buffer that contains a GPIO IO Connection resource descriptor. The format of the GPIO IO Connection resource descriptor can be found in \"GPIO Connection Descriptor\" (Section 6.4.3.8.1). The macro is designed to be used inside of a Resource Template (Section 19.3.3).", - "example": "" - }, - { - "title": "I2CSerialBusV2 (I2C Serial Bus Connection Resource Descriptor (Version 2) Macro)", - "syntax": "I2CSerialBusV2 (SlaveAddress, SlaveMode, ConnectionSpeed, AddressingMode, ResourceSource, ResourceSourceIndex, ResourceUsage, DescriptorName, Shared, VendorData)", - "arguments": "SlaveAddress is the I2C bus address for this connection. The bit field name _ADR is automatically created to refer to this portion of the resource descriptor.\nSlaveMode is an optional argument and can be either ControllerInitiated or DeviceInitiated.\nControllerInitiated is the default. The bit field name _SLV is automatically created to refer to this portion of the resource descriptor.\nConnectionSpeed is the maximum connection speed supported by this connection, in hertz. The bit field name _SPE is automatically created to refer to this portion of the resource descriptor.\nAddressingMode is an optional argument and can be either AddressingMode7Bit or\nAddressingMode10Bit. AddressingMode7Bit is the default. The bit field name _MOD is automatically created to refer to this portion of the resource descriptor.\nResourceSource is a string which uniquely identifies the I2C bus controller referred to by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\nResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\nResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nShared is an optional argument and can be either Shared or Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\nVendorData is an optional argument that specifies an object to be decoded by the OS driver. It is a RawDataBuffer. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.", - "description": "The I2CSerialBusV2 macro evaluates to a buffer that contains an I2C Serial Bus resource descriptor (Version 2). The macro is designed to be used inside of a ResourceTemplate (see Section 19.3.3).", - "example": "" - }, - { - "title": "If (Conditional Execution)", - "syntax": "If (Predicate) {TermList}", - "arguments": "Predicate is evaluated as an Integer.", - "description": "If the Predicate is non-zero, the term list of the If term is executed.", - "example": "The following examples all check for bit 3 in Local0 being set, and clear it if set.\n// example 1\nIf (And (Local0, 4))\n{\n XOr (Local0, 4, Local0)\n}\n// example 2\nStore (4, Local2)\nIf (And (Local0, Local2))\n{\n XOr (Local0, Local2, Local0) }" - }, - { - "title": "Include (Include Additional ASL File)", - "syntax": "Include (FilePathName)", - "arguments": "FilePathname is a StringData data type that contains the full OS file system path.", - "description": "Include another file that contains ASL terms to be inserted in the current file of ASL terms. The file must contain elements that are grammatically correct in the current scope.", - "example": " \n Include (\"dataobj.asl\")" - }, - { - "title": "Increment (Integer Increment)", - "syntax": "Increment (Addend) => Integer\nDestination = Source [Index] => ObjectReference\nAddend++ => Integer", - "arguments": "Addend is evaluated as an Integer.", - "description": "Add one to the Addend and place the result back in Addend. Equivalent to Add (Addend, 1, Addend). Overflow conditions are ignored and the result of an overflow is zero.", - "example": "" - }, - { - "title": "Index (Indexed Reference To Member Object)", - "syntax": "Index (Source, Index, Destination) => ObjectReference\nDestination = Source [Index] => ObjectReference", - "arguments": "Source is evaluated to a buffer, string, or package data type. Index is evaluated to an integer. The reference to the nth object (where n = Index) within Source is optionally stored as a reference into Destination.", - "description": "When Source evaluates to a Buffer, Index returns a reference to a Buffer Field containing the nth byte in the buffer. When Source evaluates to a String, Index returns a reference to a Buffer Field containing the nth character in the string. When Source evaluates to a Package, Index returns a reference to the nth object in the package.", - "example": "" - }, - { - "title": "IndexField (Declare Index/Data Fields)", - "syntax": "IndexField (IndexName, DataName, AccessType, LockRule, UpdateRule) {FieldUnitList}", - "arguments": "IndexName is evaluated as a Namestring and refers to a Field Unit object.\nDataName is evaluated as a Namestring and refers to a Field Unit object.\nAccessType, LockRule, UpdateRule, and FieldList are the same format as the Field term.", - "description": "Creates a series of named data objects whose data values are fields within a larger object accessed by an index/data-style reference to IndexName and DataName.\nThis encoding is used to define named data objects whose data values are fields within an index/data register pair. This provides a simple way to declare register variables that occur behind a typical index and data register pair.\nAccessing the contents of an indexed field data object will automatically occur through the DataName object by using an IndexName object aligned on an AccessType boundary, with synchronization occurring on the operation region that contains the index data variable, and on the Global Lock if specified by LockRule.\nThe value written to the IndexName register is defined to be a byte offset that is aligned on an AccessType boundary. For example, if AccessType is DWordAcc, valid index values are 0, 4, 8, etc. This value is always a byte offset and is independent of the width or access type of the DataName register.", - "example": "The following is a block of ASL sample code using IndexField:\nCreates an index/data register in system I/O space made up of 8-bit registers.\n \u2022 Creates a FET0 field within the indexed range.\nMethod (EX1) {\n // Define a 256-byte operational region in SystemIO space // and name it GIO0\n OperationRegion (GIO0, 1, 0x125, 0x100)\n // Create a field named Preserve structured as a sequence // of index and data bytes\n Field (GIO0, ByteAcc, NoLock, WriteAsZeros) {\n IDX0, 8,\n DAT0, 8,\n .\n .\n .\n }\n // Create an IndexField within IDX0 & DAT0 which has\n // FETs in the first two bits of indexed offset 0,\n // and another 2 FETs in the high bit on indexed\n // 2F and the low bit of indexed offset 30\n IndexField (IDX0, DAT0, ByteAcc, NoLock, Preserve) {\n FET0, 1, FET1, 1,\n Offset (0x2f), // skip to byte offset 2f\n , 7, // skip another 7 bits\n FET3, 1,\n FET4, 1\n }\n // Clear FET3 (index 2F, bit 7)\n Store (Zero, FET3)\n} // End EX1" - }, - { - "title": "Interrupt (Interrupt Resource Descriptor Macro)", - "syntax": "Interrupt (ResourceUsage, EdgeLevel, ActiveLevel, Shared, ResourceSourceIndex, ResourceSource, DescriptorName) {InterruptList} => Buffer", - "arguments": "ResourceUsage describes whether the device consumes the specified interrupt (ResourceConsumer) or produces it for use by a child device (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nEdgeLevel describes whether the interrupt is edge triggered (Edge) or level triggered (Level). The field DescriptorName. _HE is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Edge and \u20180\u2019 is Level.\nActiveLevel describes whether the interrupt is active-high (ActiveHigh) or active-low (ActiveLow). The field DescriptorName. _LL is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is ActiveHigh and \u20180\u2019 is ActiveLow.\nShared describes whether the interrupt can be shared with other devices (Shared) or not (Exclusive), and whether it is capable of waking the system from a low-power idle or system sleep state (SharedAndWake or ExclusiveAndWake). The field DescriptorName. _SHR is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Shared and \u20180\u2019 is Exclusive. If nothing is specified, then Exclusive is assumed.\nResourceSourceIndex evaluates to an integer between 0x00 and 0xFF and describes the resource source index. If it is not specified, then it is not generated. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource evaluates to a string which uniquely identifies the resource source. If it is not specified, it is not generated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName evaluates to a name string which refers to the entire resource descriptor.\nInterruptList is a comma-delimited list on integers, at least one value is required. Each integer represents a 32-bit interrupt number. At least one interrupt must be defined, and there may be no duplicates in the list. The field \u201cDescriptorName. _INT\u201d is automatically created to refer to this portion of the resource descriptor.", - "description": "The Interrupt macro evaluates to a buffer that contains an interrupt resource descriptor. The format of the interrupt resource descriptor can be found in Section 6.4.3.6, Extended Interrupt Descriptor. The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "IO (IO Resource Descriptor Macro)", - "syntax": "IO (Decode, AddressMin, AddressMax, AddressAlignment, RangeLength, DescriptorName) => Buffer\nArgument\nDecode describes whether the I/O range uses 10-bit decode (Decode10) or 16-bit decode (Decode16). The field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Decode16 and \u20180\u2019 is Decode10.\nAddressMin evaluates to a 16-bit integer that specifies the minimum acceptable starting address for the I/O range. It must be an even multiple of AddressAlignment. The field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMax evaluates to a 16-bit integer that specifies the maximum acceptable starting address for the I/O range. It must be an even multiple of AddressAlignment. The field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressAlignment evaluates to an 8-bit integer that specifies the alignment granularity for the I/O address assigned. The field DescriptorName. _ALN is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to an 8-bit integer that specifies the number of bytes in the I/O range. The field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "arguments": "", - "description": "The IO macro evaluates to a buffer which contains an IO resource descriptor. The format of the IO descriptor can be found in \u201cI/O Port Descriptor\u201d (page 419). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "IRQ (Interrupt Resource Descriptor Macro)", - "syntax": "IRQ (EdgeLevel, ActiveLevel, Shared, DescriptorName) {InterruptList} => Buffer", - "arguments": "EdgeLevel describes whether the interrupt is edge triggered (Edge) or level triggered (Level). The field DescriptorName. _HE is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Edge and ActiveHigh and \u20180\u2019 is Level and ActiveLow.\nActiveLevel describes whether the interrupt is active-high (ActiveHigh) or active-low (ActiveLow). The field DescriptorName. _LL is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Edge and ActiveHigh and \u20180\u2019 is Level and ActiveLow.\nShared describes whether the interrupt can be shared with other devices (Shared) or not (Exclusive), and whether it is capable of waking the system from a low-power idle or system sleep state (SharedAndWake or ExclusiveAndWake). The field DescriptorName. _SHR is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Shared and \u20180\u2019 is Exclusive. If nothing is specified, then Exclusive is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nInterruptList is a comma-delimited list of integers in the range 0 through 15, at least one value is required. There may be no duplicates in the list.", - "description": "The IRQ macro evaluates to a buffer that contains an IRQ resource descriptor. The format of the IRQ descriptor can be found in \u201cIRQ Descriptor\u201d ((page 419). The macro produces the three-byte form of the descriptor. The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "IRQNoFlags (Interrupt Resource Descriptor Macro)", - "syntax": "IRQNoFlags (DescriptorName) {InterruptList} => Buffer", - "arguments": "DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer.\nInterruptList is a comma-delimited list of integers in the range 0 through 15, at least one value is required. There may be no duplicates in the list Description\nThe IRQNoFlags macro evaluates to a buffer which contains an active-high, edge-triggered IRQ resource descriptor. The format of the IRQ descriptor can be found in IRQ Descriptor (page 419). The macro produces the two-byte form of the descriptor. The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "description": "", - "example": "" - }, - { - "title": "LAnd (Logical And)", - "syntax": "LAnd (Source1, Source2) => Boolean\nSource1 && Source2 => Boolean", - "arguments": "Source1 and Source2 are evaluated as integers.", - "description": "If both values are non-zero, True is returned: otherwise, False is returned.", - "example": "" - }, - { - "title": "LEqual (Logical Equal)", - "syntax": "LEqual (Source1, Source2) => Boolean\nSource1 == Source2 => Boolean", - "arguments": "Source1 and Source2 must each evaluate to an integer, a string, or a buffer. The data type of Source1 dictates the required type of Source2. Source2 is implicitly converted if necessary to match the type of Source1.", - "description": "If the values are equal, True is returned; otherwise, False is returned. For integers, a numeric compare is performed. For strings and buffers, True is returned only if both lengths are the same and the result of a byte-wise compare indicates exact equality.", - "example": "" - }, - { - "title": "LGreater (Logical Greater)", - "syntax": "LGreater (Source1, Source2) => Boolean\nSource1 > Source2 => Boolean", - "arguments": "Source1 and Source2 must each evaluate to an integer, a string, or a buffer. The data type of Source1 dictates the required type of Source2. Source2 is implicitly converted if necessary to match the type of Source1.", - "description": "If Source1 is greater than Source2, True is returned; otherwise, False is returned. For integers, a numeric comparison is performed. For strings and buffers, a lexicographic comparison is performed. True is returned if a byte-wise (unsigned) compare discovers at least one byte in Source1 that is numerically greater than the corresponding byte in Source2. False is returned if at least one byte in Source1 is numerically less than the corresponding byte in Source2. In the case of byte-wise equality, True is returned if the length of Source1 is greater than Source2, False is returned if the length of Source1 is less than or equal to Source2.", - "example": "" - }, - { - "title": "LGreaterEqual (Logical Greater Than Or Equal)", - "syntax": "LGreaterEqual (Source1, Source2) => Boolean\nSource1 >= Source2 => Boolean", - "arguments": "Source1 and Source2 must each evaluate to an integer, a string, or a buffer. The data type of Source1 dictates the required type of Source2. Source2 is implicitly converted if necessary to match the type of Source1.", - "description": "If Source1 is greater than or equal to Source2, True is returned; otherwise, False is returned. Equivalent to LNot(LLess()). See the description of the LLess operator.", - "example": "" - }, - { - "title": "LLess (Logical Less)", - "syntax": "LLess (Source1, Source2) => Boolean\nSource1 < Source2 => Boolean", - "arguments": "Source1 and Source2 must each evaluate to an integer, a string, or a buffer. The data type of Source1 dictates the required type of Source2. Source2 is implicitly converted if necessary to match the type of Source1.", - "description": "If Source1 is less than Source2, True is returned; otherwise, False is returned. For integers, a numeric comparison is performed. For strings and buffers, a lexicographic comparison is performed. True is returned if a byte-wise (unsigned) compare discovers at least one byte in Source1 that is numerically less than the corresponding byte in Source2. False is returned if at least one byte in Source1 is numerically greater than the corresponding byte in Source2. In the case of byte-wise equality, True is returned if the length of Source1 is less than Source2, False is returned if the length of Source1 is greater than or equal to Source2.", - "example": "" - }, - { - "title": "LLessEqual (Logical Less Than Or Equal)", - "syntax": "LLessEqual (Source1, Source2) => Boolean\nSource1 <= Source2 => Boolean", - "arguments": "Source1 and Source2 must each evaluate to an integer, a string, or a buffer. The data type of Source1 dictates the required type of Source2. Source2 is implicitly converted if necessary to match the type of Source1.", - "description": "If Source1 is less than or equal to Source2, True is returned; otherwise False is returned. Equivalent to LNot(LGreater()). See the description of the LGreater operator.", - "example": "" - }, - { - "title": "LNot (Logical Not)", - "syntax": "LNot (Source) => Boolean\n!Source => Boolean", - "arguments": "Source is evaluated as an integer.", - "description": "If the value is zero True is returned; otherwise, False is returned.", - "example": "" - }, - { - "title": "LNotEqual (Logical Not Equal) )", - "syntax": "LNotEqual (Source1, Source2) => Boolean\nSource1 != Source2 => Boolean", - "arguments": "Source1 and Source2 must each evaluate to an integer, a string, or a buffer. The data type of Source1 dictates the required type of Source2. Source2 is implicitly converted if necessary to match the type of Source1.", - "description": "If Source1 is not equal to Source2, True is returned; otherwise False is returned. Equivalent to LNot(LEqual()).See the description of the LEqual operator.", - "example": "" - }, - { - "title": "Load (Load Definition Block)", - "syntax": "Load (Object, DDBHandle)", - "arguments": "The Object parameter can refer to one of the following object types:\n1. An operation region field\n2. An operation region directly\n3. An ASL Buffer object\nIf the object is an operation region, the operation region must be in SystemMemory space. The Definition Block should contain an ACPI DESCRIPTION_HEADER of type SSDT.\nThe Definition Block must be totally contained within the supplied operation region, operation region field, or Buffer object. OSPM reads this table into memory, the checksum is verified, and then it is loaded into the ACPI namespace.", - "description": "Performs a run-time load of a Definition Block. Any table loaded via an operation region must be in memory marked as AddressRangeReserved or AddressRangeNVS. The OS can also check the OEM Table ID and Revision ID against a database for a newer revision Definition Block of the same OEM Table ID and load it instead.\nThe default namespace location to load the Definition Block is relative to the root of the namespace. The new Definition Block can override this by specifying absolute names or by adjusting the namespace location using the Scope operator.\nLoading a Definition Block is a synchronous operation. Upon completion of the operation, the Definition Block has been loaded. The control methods defined in the Definition Block are not executed during load time.", - "example": "" - }, - { - "title": "LoadTable (Load Definition Block From XSDT)", - "syntax": "LoadTable (SignatureString, OEMIDString, OEMTableIDString, RootPathString, ParameterPathString, ParameterData) => DDBHandle", - "arguments": "The XSDT is searched for a table where the Signature field matches SignatureString, the OEM ID field matches OEMIDString, and the OEM Table ID matches OEMTableIDString. All comparisons are case sensitive. If the SignatureString is greater than four characters, the OEMIDString is greater than six characters, or the OEMTableID is greater than eight characters, a run-time error is generated. The OS can also check the OEM Table ID and Revision ID against a database for a newer revision Definition Block of the same OEM Table ID and load it instead.\nThe RootPathString specifies the root of the Definition Block. It is evaluated using normal scoping rules, assuming that the scope of the LoadTable instruction is the current scope. The new Definition Block can override this by specifying absolute names or by adjusting the namespace location using the Scope operator. If RootPathString is not specified, \u201c\\\u201d is assumed\nIf ParameterPathString and ParameterData are specified, the data object specified by ParameterData is stored into the object specified by ParameterPathString after the table has been added into the namespace. If the first character of ParameterPathString is a backslash (\u2018\\\u2019) or caret (\u2018^\u2019) character, then the path of the object is ParameterPathString. Otherwise, it is RootPathString.ParameterPathString. If the specified object does not exist, a run-time error is generated.\nThe handle of the loaded table is returned. If no table matches the specified signature, then 0 is returned.", - "description": "Performs a run-time load of a Definition Block from the XSDT. Any table referenced by LoadTable must be in memory marked by AddressRangeReserved or AddressRangeNVS.\nNote: OSPM loads the DSDT and all SSDTs during initialization. As such, Definition Blocks to be conditionally loaded via LoadTable must contain signatures other than \u201cSSDT\u201d.\nLoading a Definition Block is a synchronous operation. Upon completion of the operation, the Definition Block has been loaded. The control methods defined in the Definition Block are not executed during load time.", - "example": " Store (LoadTable (\u201cOEM1\u201d, \u201dMYOEM\u201d, \u201dTABLE1\u201d, \u201d\\\\_SB.PCI0\u201d,\u201dMYD\u201d,\n Package () {0,\u201d\\\\_SB.PCI0\u201d}), Local0)\nThis operation would search through the RSDT or XSDT for a table with the signature \u201cOEM1,\u201d the OEM ID of \u201cMYOEM,\u201d and the table ID of \u201cTABLE1.\u201d If not found, it would store Zero in Local0. Otherwise, it will store a package containing 0 and \u201c\\\\_SB.PCI0\u201d into the variable at \\_SB.PCI0.MYD." - }, - { - "title": "Localx (Method Local Data Objects)", - "syntax": "Local0 | Local1 | Local2 | Local3 | Local4 | Local5 | Local6 | Local7", - "arguments": "", - "description": "Up to 8 local objects can be referenced in a control method. On entry to a control method, these objects are uninitialized and cannot be used until some value or reference is stored into the object. Once initialized, these objects are preserved in the scope of execution for that control method.", - "example": "" - }, - { - "title": "LOr (Logical Or)", - "syntax": "LOr (Source1, Source2) => Boolean\nSource1 || Source2 => Boolean", - "arguments": "Source1 and Source2 are evaluated as integers.", - "description": "If either value is non-zero, True is returned; otherwise, False is returned.", - "example": "" - }, - { - "title": "Match (Find Object Match)", - "syntax": "Match (SearchPackage, Op1, MatchObject1, Op2, MatchObject2, StartIndex) => Ones | Integer", - "arguments": "SearchPackage is evaluated to a package object and is treated as a one-dimension array. Each package element must evaluate to either an integer, a string, or a buffer. Uninitialized package elements and elements that do not evaluate to integers, strings, or buffers are ignored. Op1 and Op2 are match operators. MatchObject1 and MatchObject2 are the objects to be matched and must each evaluate to either an integer, a string, or a buffer. StartIndex is the starting index within the SearchPackage.", - "description": "A comparison is performed for each element of the package, starting with the index value indicated by StartIndex (0 is the first element). If the element of SearchPackage being compared against is called P[i], then the comparison is:\nIf (P[i] Op1 MatchObject1) and (P[i] Op2 MatchObject2) then Match => i is returned.\nIf the comparison succeeds, the index of the element that succeeded is returned; otherwise, the constant object Ones is returned. The data type of the MatchObject dictates the required type of the package element. If necessary, the package element is implicitly converted to match the type of the MatchObject. If the implicit conversion fails for any reason, the package element is ignored (no match.)\nOp1 and Op2 have the values and meanings listed in the following table.\nTable 19-432 Match Term Operator Meanings\nOperator\nEncoding\nMacro\nTRUE A don\u2019t care, always returns TRUE\n0\nMTR\nEQ Returns TRUE if P[i] == MatchObject\n1\nMEQ\nLE Returns TRUE if P[i] <= MatchObject\n2\nMLE\nLT Returns TRUE if P[i] < MatchObject\n3\nMLT\nGE Returns TRUE if P[i] >= MatchObject\n4\nMGE\nGT Returns TRUE if P[i] > MatchObject\n5\nMGT", - "example": "Following are some example uses of Match:\nName (P1,\n Package () {1981, 1983, 1985, 1987, 1989, 1990, 1991, 1993, 1995, 1997, 1999,\n2001}\n)\n// match 1993 == P1[i]\nMatch (P1, MEQ, 1993, MTR, 0, 0) // -> 7, since P1[7] == 1993\n// match 1984 == P1[i]\nMatch (P1, MEQ, 1984, MTR, 0, 0) // -> ONES (not found)\n// match P1[i] > 1984 and P1[i] <= 2000\nMatch (P1, MGT, 1984, MLE, 2000, 0) // -> 2, since P1[2]>1984 and P1[2]<=2000\n// match P1[i] > 1984 and P1[i] <= 2000, starting with 3rd element\nMatch (P1, MGT, 1984, MLE, 2000, 3) // -> 3, first match at or past Start" - }, - { - "title": "Memory24 (Memory Resource Descriptor Macro)", - "syntax": "Memory24 (ReadAndWrite, AddressMinimum, AddressMaximum, AddressAlignment, RangeLength, DescriptorName)", - "arguments": "ReadAndWrite specifies whether or not the memory region is read-only (ReadOnly) or read/write (ReadWrite). If nothing is specified, then ReadWrite is assumed. The 1-bit field DescriptorName._RW is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is ReadWrite and \u20180\u2019 is ReadOnly.\nAddressMinimum evaluates to a 16-bit integer that specifies bits [8:23] of the lowest possible base address of the memory range. All other bits are assumed to be zero. The value must be an even multiple of AddressAlignment. The 16-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 16-bit integer that specifies bits [8:23] of the highest possible base address of the memory range. All other bits are assumed to be zero. The value must be an even multiple of AddressAlignment. The 16-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressAlignment evaluates to a 16-bit integer that specifies bits [0:15] of the required alignment for the memory range. All other bits are assumed to be zero. The address selected must be an even multiple of this value. The 16-bit field DescriptorName. _ALN is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 16-bit integer that specifies the total number of bytes decoded in the memory range. The 16-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor. The range length provides the length of the memory range in 256 byte blocks.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The Memory24 macro evaluates to a buffer which contains an 24-bit memory descriptor. The format of the 24-bit memory descriptor can be found in \u201c24-Bit Memory Range Descriptor \u201d (page 426). The macro is designed to be used inside of a ResourceTemplate (page 1033).\nNote: The use of Memory24 is deprecated and should not be used in new designs.", - "example": "" - }, - { - "title": "Memory32 (Memory Resource Descriptor Macro)", - "syntax": "Memory32 (ReadAndWrite, AddressMinimum, AddressMaximum, AddressAlignment, RangeLength, DescriptorName)", - "arguments": "ReadAndWrite specifies whether or not the memory region is read-only (ReadOnly) or read/write (ReadWrite). If nothing is specified, then ReadWrite is assumed. The 1-bit field DescriptorName._RW is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is ReadWrite and \u20180\u2019 is ReadOnly.\nAddressMinimum evaluates to a 32-bit integer that specifies the lowest possible base address of the memory range. The value must be an even multiple of AddressAlignment. The 32-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 32-bit integer that specifies the highest possible base address of the memory range. The value must be an even multiple of AddressAlignment. The 32-bit field\nDescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressAlignment evaluates to a 32-bit integer that specifies the required alignment for the memory range. The address selected must be an even multiple of this value. The 32-bit field DescriptorName. _ALN is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 32-bit integer that specifies the total number of bytes decoded in the memory range. The 32-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor. The range length provides the length of the memory range in 1 byte blocks.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The Memory32 macro evaluates to a buffer which contains a 32-bit memory descriptor, which describes a memory range with a minimum, a maximum and an alignment. The format of the 32-bit memory descriptor can be found in \u201c32-Bit Memory Range Descriptor \u201d (page 427). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "Memory32Fixed (Memory Resource Descriptor Macro)", - "syntax": "Memory32Fixed (ReadAndWrite, AddressBase, RangeLength, DescriptorName)", - "arguments": "ReadAndWrite specifies whether or not the memory region is read-only (ReadOnly) or read/write (ReadWrite). If nothing is specified, then ReadWrite is assumed. The 1-bit field DescriptorName._RW is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is ReadWrite and \u20180\u2019 is ReadOnly.\nAddressBase evaluates to a 32-bit integer that specifies the base address of the memory range. The 32bit field DescriptorName. _BAS is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 32-bit integer that specifies the total number of bytes decoded in the memory range. The 32-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The Memory32Fixed macro evaluates to a buffer which contains a 32-bit memory descriptor, which describes a fixed range of memory addresses. The format of the fixed 32-bit memory descriptor can be found in 32-Bit Fixed Memory Range Descriptor (page 429). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "Method (Declare Control Method)", - "syntax": "Method (MethodName, NumArgs, SerializeRule, SyncLevel, ReturnType, ParameterTypes) {TermList}", - "arguments": "MethodName is evaluated as a Namestring data type.\nNumArgs is optional and is the required number of arguments to be passed to the method, evaluated as an Integer data type. If not specified, the default value is zero arguments. Up to 7 arguments may be passed to a method. These arguments may be referenced from within the method as Arg0 through Arg6.\nSerializeRule is optional and is a flag that defines whether the method is serialized or not and is one of the following: Serialized or NotSerialized. A method that is serialized cannot be reentered by additional threads. If not specified, the default is NotSerialized.\nSyncLevel is optional and specifies the synchronization level for the method (0 15). If not specified, the default sync level is zero.\nReturnType is optional and specifies the type(s) of the object(s) returned by the method. If the method does not return an object, then nothing is specified or UnknownObj is specified. To specify a single return type, simply use the ObjectTypeKeyword (e.g. IntObj, PkgObj, etc.). To specify multiple possible return types, enclose the comma-separated ObjectTypeKeywords with braces. For example: {IntObj, BuffObj}.\nParameterTypes is optional and specifies the type of the method parameters. It is a comma-separated, variable-length list of the expected object type or types for each of the method parameters, enclosed in braces. For each parameter, the parameter type consists of either an ObjectTypeKeyword or a commaseparated sub-list of ObjectTypeKeywords enclosed in braces. If ParameterTypes is specified, the number of parameters must match NumArgs.\nTermList is a variable-length list of executable ASL statements representing the body of the control method.", - "description": "Creates a new control method of name MethodName. This is a named package containing a series of object references that collectively represent a control method, which is a procedure that can be invoked to perform computation. Method opens a name scope.\nSystem software executes a control method by referencing the objects in the package in order. For more information on method execution, see Section 5.5.2, \u201cControl Method Execution.\u201d\nThe current namespace location used during name creation is adjusted to be the current location on the namespace tree. Any names created within this scope are \u201cbelow\u201d the name of this package. The current namespace location is assigned to the method package, and all namespace references that occur during control method execution for this package are relative to that location.\nIf a method is declared as Serialized, an implicit mutex associated with the method object is acquired at the specified SyncLevel. If no SyncLevel is specified, SyncLevel 0 is assumed. The serialize rule can be used to prevent reentering of a method. This is especially useful if the method creates namespace objects.\nWithout the serialize rule, the reentering of a method will fail when it attempts to create the same namespace object.\nThere are eight local variables automatically available for each method, referenced as Local0 through Local7. These locals may be used to store any type of ASL object.\nAlso notice that all namespace objects created by a method have temporary lifetime. When method execution exits, the created objects will be destroyed.", - "example": "The following block of ASL sample code shows a use of Method for defining a control method that turns on a power resource.\nMethod (_ON) {\n Store (One, GIO.IDEP) // assert power Sleep (10) // wait 10ms\n Store (One, GIO.IDER) // de-assert reset#\n Stall (10) // wait 10us\n Store (Zero, GIO.IDEI) // de-assert isolation }\nThis method is an implementation of _SRS (Set Resources). It shows the use of a method argument and two method locals.\nMethod (_SRS, 1, NotSerialized)\n{\n CreateWordField (Arg0, One, IRQW)\n Store (\\_SB.PCI0.PID1.IENA, Local1)\n Or (IRQW, Local1, Local1)\n Store (Local1, \\_SB.PCI0.PID1.IENA)\n FindSetRightBit (IRQW, Local0)\n If (Local0)\n {\n Decrement (Local0)\n Store (Local0, \\_SB.PCI0.PID1.IN01)\n }\n}" - }, - { - "title": "Mid (Extract Portion of Buffer or String)", - "syntax": "Mid (Source, Index, Length, Result) => Buffer or String", - "arguments": "Source is evaluated as either a Buffer or String. Index and Length are evaluated as Integers.", - "description": "If Source is a buffer, then Length bytes, starting with the Indexth byte (zero-based) are optionally copied into Result. If Index is greater than or equal to the length of the buffer, then the result is an empty buffer. Otherwise, if Index + Length is greater than or equal to the length of the buffer, then only bytes up to and including the last byte are included in the result.\nIf Source is a string, then Length characters, starting with the Indexth character (zero-based) are optionally copied into Result. If Index is greater than or equal to the length of the buffer, then the result is an empty string. Otherwise, if Index + Length is greater than or equal to the length of the string, then only bytes up to an including the last character are included in the result.", - "example": "" - }, - { - "title": "Mod (Integer Modulo)", - "syntax": "Mod (Dividend, Divisor, Result) => Integer\nResult = Dividend % Divisor => Integer\nResult %= Divisor => Integer", - "arguments": "Dividend and Divisor are evaluated as Integers.", - "description": "The Dividend is divided by Divisor, and then the resulting remainder is optionally stored into Result. If Divisor evaluates to zero, a fatal exception is generated.", - "example": "" - }, - { - "title": "Multiply (Integer Multiply)", - "syntax": "Multiply (Multiplicand, Multiplier, Result) => Integer\nResult = Multiplicand * Multiplier => Integer\nResult *= Multiplier => Integer", - "arguments": "Multiplicand and Multiplier are evaluated as Integers.", - "description": "The Multiplicand is multiplied by Multiplier and the result is optionally stored into Result. Overflow conditions are ignored and results are undefined.", - "example": "" - }, - { - "title": "Mutex (Declare Synchronization/Mutex Object)", - "syntax": "Mutex (MutexName, SyncLevel)", - "arguments": "The MutexName is evaluated as a Namestring data type.\nThe SyncLevel is optional and specifies the logical nesting level of the Mutex synchronization object. The current sync level is maintained internally for a thread, and represents the greatest SyncLevel among mutex objects that are currently acquired by the thread. The SyncLevel of a thread, before acquiring any mutexes, is zero. The SyncLevel of the Global Lock (\\_GL) is zero. If not specified, the default sync level value is zero.", - "description": "Creates a data mutex synchronization object named MutexName, with a synchronization level from 0 to 15 as specified by the Integer SyncLevel.\nA mutex synchronization object provides a control method with a mechanism for waiting for certain events. To prevent deadlocks, wherever more than one synchronization object must be owned, the synchronization objects must always be released in the order opposite the order in which they were acquired.\nThe SyncLevel parameter declares the logical nesting level of the synchronization object. The current sync level is maintained internally for a thread, and represents the greatest SyncLevel among mutex objects that are currently acquired by the thread. The SyncLevel of a thread before acquiring any mutexes is zero. The SyncLevel of the Global Lock (\\_GL) is zero.\nAll Acquire terms must refer to a synchronization object with a SyncLevel that is equal or greater than the current level, and all Release terms must refer to a synchronization object with a SyncLevel that is equal to the current level.\nMutex synchronization provides the means for mutually exclusive ownership. Ownership is acquired using an Acquire term and is released using a Release term. Ownership of a Mutex must be relinquished before completion of any invocation. For example, the top-level control method cannot exit while still holding ownership of a Mutex. Acquiring ownership of a Mutex can be nested (can be acquired multiple times by the same thread).", - "example": "" - }, - { - "title": "Name (Declare Named Object)", - "syntax": "Name (ObjectName, Object)", - "arguments": "Creates a new object named ObjectName. Attaches Object to ObjectName in the Global ACPI namespace.", - "description": "Creates ObjectName in the namespace, which references the Object.", - "example": "The following example creates the name PTTX in the root of the namespace that references a package.\nName (\\PTTX, // Port to Port Translate Table\n Package () {Package () {0x43, 0x59}, Package) {0x90, 0xFF}} )\nThe following example creates the name CNT in the root of the namespace that references an integer data object with the value 5.\nName (\\CNT, 5)" - }, - { - "title": "NAnd (Integer Bitwise Nand)", - "syntax": "NAnd (Source1, Source2, Result) => Integer", - "arguments": "Source1 and Source2 are evaluated as Integers.", - "description": "A bitwise NAND is performed and the result is optionally stored in Result.", - "example": "" - }, - { - "title": "NoOp Code (No Operation)", - "syntax": "NoOp", - "arguments": "", - "description": "This operation has no effect.", - "example": "" - }, - { - "title": "NOr (Integer Bitwise Nor)", - "syntax": "NOr (Source1, Source2, Result) => Integer", - "arguments": "Source1 and Source2 are evaluated as Integers.", - "description": "A bitwise NOR is performed and the result is optionally stored in Result.", - "example": "" - }, - { - "title": "Not (Integer Bitwise Not)", - "syntax": "Not (Source, Result) => Integer\nResult = ~Source => Integer", - "arguments": "Source is evaluated as an integer data type.\nA bitwise NOT is performed and the result is optionally stored in Result.", - "description": "", - "example": "" - }, - { - "title": "Notify (Notify Object of Event)", - "syntax": "Notify (Object, NotificationValue)", - "arguments": "Notifies the OS that the NotificationValue for the Object has occurred. Object must be a reference to a device, processor, or thermal zone object.", - "description": "Object type determines the notification values. For example, the notification values for a thermal zone object are different from the notification values used for a device object. Undefined notification values are treated as reserved and are ignored by the OS.\nFor lists of defined Notification values, see Section 5.6.6, \u201cDevice Object Notifications.\u201d", - "example": "" - }, - { - "title": "Offset (Change Current Field Unit Offset)", - "syntax": "Offset (ByteOffset)", - "arguments": "ByteOffset is the new offset (in bytes) for the next FieldUnit within a FieldList.", - "description": "The Offset operator is used within a FieldList to specify the byteOffset of the next defined field within its parent operation region. This can be used instead of defining the bit lengths that need to be skipped. All offsets are defined starting from zero, based at the starting address of the parent region.", - "example": "" - }, - { - "title": "ObjectType (Get Object Type)", - "syntax": "ObjectType (Object) => Integer", - "arguments": "Object is any valid object.", - "description": "The execution result of this operation is an integer that has the numeric value of the object type for Object.\nThe object type codes are listed in Table 18-20. Notice that if this operation is performed on an object reference such as one produced by the Alias, Index, or RefOf statements, the object type of the base object is returned. For typeless objects such as predefined scope names (in other words, \\_SB, \\_GPE, etc.), the type value 0 (Uninitialized) is returned.\nTable 19-433 TValues Returned By the ObjectType Operator\nValue\nObject\n0\nUninitialized\n1\nInteger\n2\nString\n3\nBuffer\n4\nPackage\n5\nField Unit\n6\nDevice\n7\nEvent\n8\nMethod\n9\nMutex\n10\nOperation Region\n11\nPower Resource\n12\nProcessor\n13\nThermal Zone\n14\nBuffer Field\n15\nDDB Handle\n16\nDebug Object\n>16\nReserved", - "example": "" - }, - { - "title": "One (Constant One Integer)", - "syntax": "One=> Integer", - "arguments": "", - "description": "The One operator returns an Integer with the value 1. Writes to this object are not allowed. The use of this operator can reduce AML code size, since it is represented by a one-byte AML opcode.", - "example": "" - }, - { - "title": "Ones (Constant Ones Integer)", - "syntax": "Ones=> Integer\nThe Ones operator returns an Integer with all bits set to 1. Writes to this object are not allowed. The use of this operator can reduce AML code size, since it is represented by a one-byte AML opcode.\nNote: The actual value of the integer returned by the Ones operator depends on the integer width of the\nDSDT. If the revision of the DSDT is 1 or less, the integer width is 32 bits and Ones returns 0xFFFFFFFF. If the revision of the DSDT is 2 or greater, the integer width is 64 bits and Ones returns 0xFFFFFFFFFFFFFFFF. This difference must be considered when performing comparisons against the Ones Integer.", - "arguments": "", - "description": "", - "example": "" - }, - { - "title": "OperationRegion (Declare Operation Region)", - "syntax": "OperationRegion (RegionName, RegionSpace, Offset, Length)", - "arguments": "Declares an operation region named RegionName. Offset is the offset within the selected RegionSpace at which the region starts (byte-granular), and Length is the length of the region in bytes.", - "description": "An Operation Region is a type of data object where read or write operations to the data object are performed in some hardware space. For example, the Definition Block can define an Operation Region within a bus, or system I/O space. Any reads or writes to the named object will result in accesses to the I/ O space.\nOperation regions are regions in some space that contain hardware registers for exclusive use by ACPI control methods. In general, no hardware register (at least byte-granular) within the operation region accessed by an ACPI control method can be shared with any accesses from any other source, with the exception of using the Global Lock to share a region with the firmware. The entire Operation Region can be allocated for exclusive use to the ACPI subsystem in the host OS.\nOperation Regions that are defined within the scope of a method are the exception to this rule. These Operation Regions are known as \u201cDynamic\u201d since the OS has no idea that they exist or what registers they use until the control method is executed. Using a Dynamic SystemIO or SystemMemory Operation Region is not recommended since the OS cannot guarantee exclusive access. All other types of Operation Regions may be Dynamic.\nOperation Regions define the overall base address and length of a hardware region, but they cannot be accessed directly by AML code. A Field object containing one or more FieldUnits is used to overlay the Operation Region in order to access individual areas of the Region. An individual FieldUnit within an Operation Region may be as small as one bit, or as large as the length of the entire Region. FieldUnit values are normalized (shifted and masked to the proper length.) The data type of a FieldUnit can be either a Buffer or an Integer, depending on the bit length of the FieldUnit. If the FieldUnit is smaller than or equal to the size of an Integer (in bits), it will be treated as an Integer. If the FieldUnit is larger than the size of an Integer, it will be treated as a Buffer. The size of an Integer is indicated by the DSDT header\u2019s Revision field. A revision less than 2 indicates that the size of an Integer is 32 bits. A value greater than or equal to 2 signifies that the size of an Integer is 64 bits. For more information about data types and FieldUnit type conversion rules, see Section 19.3.5.7, \u201cData Type Conversion Rules\u201d.\nAn Operation Region object implicitly supports Mutex synchronization. Updates to the object, or a Field data object for the region, will automatically synchronize on the Operation Region object; however, a control method may also explicitly synchronize to a region to prevent other accesses to the region (from other control methods). Notice that according to the control method execution model, control method execution is non-preemptive. Because of this, explicit synchronization to an Operation Region needs to be done only in cases where a control method blocks or yields execution and where the type of register usage requires such synchronization.\nThe predefined Operation Region types specified in ACPI are shown in the Table 5-160 on page 275.", - "example": "The following example ASL code shows the use of OperationRegion combined with Field to describe IDE 0 and 1 controlled through general I/O space, using one FET.\nOperationRegion (GIO, SystemIO, 0x125, 0x1)\nField (GIO, ByteAcc, NoLock, Preserve) {\n IDEI, 1, // IDEISO_EN - isolation buffer\n IDEP, 1, // IDE_PWR_EN - power\n IDER, 1 // IDERST#_EN - reset# }" - }, - { - "title": "Or (Integer Bitwise Or)", - "syntax": "Or (Source1, Source2, Result) => Integer\nResult = Source1 | Source2 => Integer\nResult |= Source1 => Integer", - "arguments": "Source1 and Source2 are evaluated as Integers.", - "description": "A bitwise OR is performed and the result is optionally stored in Result.", - "example": "" - }, - { - "title": "Package (Declare Package Object)", - "syntax": "Package (NumElements) {PackageList} => Package", - "arguments": "NumElements is evaluated as an Integer. PackageList is an initializer list of objects.\nDeclares an unnamed aggregation of named data items, constants, and/or references to non-data namespace objects. The size of the package is NumElements. The PackageList contains the data items, constants, and/or object references used to initialize the package.\nIf NumElements is absent, it is automatically set by the ASL compiler to match the number of elements in the PackageList. If NumElements is present and greater than the number of elements in the PackageList, the default entry of type Uninitialized (see ObjectType) is used to initialize the package elements beyond those initialized from the PackageList.\nThere are three types of package elements allowed in the PackageList: ConstantData Objects(Integers, Strings, Buffers, and Packages), named references that resolve to Data Objects (Integers, Strings, Buffers, and Packages), and named references to objects other than Data Objects.\nThese constant terms are resolved at ASL compile time:\n\u2022 Integer Constant\n\u2022 String Constant\n\u2022 Buffer Constant\n\u2022 Package Constant\nThese Named References to Data Objects are resolved to actual data by the AML Interpreter at runtime:\n\u2022 Integer reference\n\u2022 String reference\n\u2022 Buffer reference\n\u2022 Buffer Field reference\n\u2022 Field Unit reference\n\u2022 Package reference\nThese Named References to non-Data Objects cannot be resolved to values. They are instead returned in the package as references:\n\u2022 Device reference\n\u2022 Event reference\n\u2022 Method reference\n\u2022 Mutex reference\n\u2022 Operation Region reference\n\u2022 Power Resource reference\n\u2022 Processor reference\n\u2022 Thermal Zone reference\nNote: For Package elements of type Package (defining a subpackage), individual elements of the subpackage are resolved according to the rules above, both compile-time and runtime.\nEvaluating an uninitialized element will yield a runtime error, but elements can be assigned values at runtime to define them (via the Index operator). It is a compile time error for NumElements to be less than the number of elements defined in the PackageList.\nThe ASL compiler can emit two different AML opcodes for a Package declaration, either PackageOp or VarPackageOp. For small, fixed-length packages, the PackageOp is used and this opcode is compatible with ACPI 1.0. A VarPackageOp will be emitted if any of the following conditions are true:\n\u2022 The NumElements argument is a TermArg that can only be resolved at runtime.\n\u2022 At compile time, NumElements resolves to a constant that is larger than 255.\n\u2022 The PackageList contains more than 255 initializer elements.", - "description": "", - "example": "Name (INT1, 0x1234)\nProcessor (CPU0, 0, 0x1010, 6) {}\nPowerResource (PWR1, 0, 0) {}\nName (PKG1, Package () {\n 0x3400, // Integer Constant, resolved at compile time\n \"Processor\" // String Constant, resolved at compile time\n \\INT1 // Integer Reference, resolved to value at\n // runtime\n \\CPU0 // Object Reference, returned as a reference\n // object\n Package () { // Package Constant. Elements are resolved at\n // both compile time and runtime\n 0x4321, // Integer Constant, resolved at compile time\n \\INT1, // Integer Reference, resolved to value at\n // runtime\n \\PWR1\n })\nThe runtime values of the parent package and subpackages are:\nPackage [Contains 0x05 Elements]\n(00) Integer 0x0000000000003400\n(01) String [0x09] \"Processor\"\n(02) Integer 0x0000000000001234\n(03) Reference [Named Object] [CPU0] Processor\n(04) Package [Contains 0x03 Elements]\n(00) Integer 0x0000000000004321\n(01) Integer 0x0000000000001234\n(02) Reference [Named Object] [PWR1] Power}" - }, - { - "title": "PinConfig (Pin Configuration)", - "syntax": "Macro:\nPinConfig (Shared/Exclusive, PinConfigType, PinConfigValue, ResourceSource,\nResourceSourceIndex, ResourceUsage, DescriptorName, VendorData) {Pin List}", - "arguments": "\u2022 Shared is an optional argument and can be either Shared or Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinConfigType can be one of the configuration types described below in Table 19-434. The bit field _TYP is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinConfigValue is one of the configurations values described below in Table 19-434. The bit field _VAL is automatically created to refer to this portion of the resource descriptor.\n\u2022 ResourceSource is a string which uniquely identifies the pin controller referred to by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\n\u2022 ResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\n\u2022 ResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.\n\u2022 DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\n\u2022 VendorData is an optional argument that specifies a RawDataBuffer containing vendor-defined byte data to be decoded by the OS driver. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinList is a list of pin numbers on the ResourceSource that are described by this descriptor. The bit field name _PIN is automatically created to refer to this portion of the resource descriptor.\nTable 19-434 Pin Configuration Types and Values\nPin Configuration Type\nPin Configuration Value", - "description": "0x00 = Default\nN/A\nDefault configuration. No configuration is applied.\n0x01 = Bias Pull-Up\nPull up resistance, in\nOhms.\nThis means the pin is pulled up with a certain number of Ohms to an implicitly supplied VDD rail.\n0x02 = Bias Pull-down\nPull down resistance, in Ohms.\nThis means the pin is pulled down with a certain number of Ohms, toward the GND rail.\n0x03 = Bias Default\nN/A\nIf the silicon has a default biasing mode, reset the pin to this mode.\n0x04 = Bias Disable\nN/A\nAny software-selectable bias settings on the pin will be disabled.\n0x05 = Bias High Impedance\nN/A\nThis means that the pin is configured into a high impedance mode and essentially shut off from the outside world. It will not influence the signal state if a rail is connected to the pin, hence a good default mode.\n0x06 = Bias Bus Hold\nN/A\nThis will make the pin in a weak latch state where it weakly drives the last value on a tristate bus.\n0x07 = Drive Open Drain\nN/A\nThis will configure the pin into open drain (open collector) state.\nPin Configuration Type\nPin Configuration Value\n0x08 = Drive Open Source\nN/A\nThis will configure the pin into open source (open emitter) state.\n0x09 = Drive Push Pull\nN/A\nThis will configure the pin into explicit push-pull state. This is useful if the power-on default state is e.g. open drain or high impedance state.\n0x0A = Drive Strength\nDrive strength in milliamperes\nThis will set the output driver of the pin to supply a certain number of milliamperes, usually by activating several driver stages.\n0x0B = Slew Rate\nCustom format\nThis controls the slew rate of the pin, affecting speed but also sharpness of edges and thus noisiness on the board. The hardware-specific argument tells what slew rate to configure\n0x0C = Input Debounce\nDebounce time in microseconds.\nThis will enable debouncing (for e.g. key inputs) of the pin signal.\n0x0D = Input Schmitt Trigger\nEnabled = 1, Disabled = 0\nThis will enable Schmitt trigger support for the line.\n0x0E 0x7F = Reserved\nReserved\nReserved\n0x80 0xFF = Vendor defined values\nCustom base\nFrom this point, vendor and Hardware-specific configurations are listed.\nThe PinConfig macro evaluates to a buffer that contains a Pin Configuration resource descriptor. The format of the Pin Configuration resource descriptor can be found in \u201cPin Configuration Descriptor\u201d on page 462. The macro is designed to be used inside of an ASL Resource Template (Section 19.3.3).\nNote: There is some overlap between the properties set by GpioIo/GpioInt/ PinFunction and PinConfig descriptors. For example, both are setting properties such as pull-ups. If the same property is specified by multiple descriptors for the same pins, the order in which these properties are applied is undetermined. To avoid any conflicts, GpioInt/GpioIo/PinFunction should provide a default value for these properties when PinConfig is used. If PinConfig is used to set pin bias, PullDefault should be used for GpioIo/GpioInt/ PinFunction. If PinConfig is used to set debounce timeout, 0 should be used for GpioIo/GpioInt. If PinConfig is used to set drive strength, 0 should be used for GpioIo.", - "example": "//\n// Description: GPIO\n//\nDevice (GPI0)\n{\n Name (_HID, \"PNPFFFE\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4FE00000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x54}\n })\n Return(RBUF)\n}\n}\n//\n// Description: I2C controller 1\n//\nDevice (I2C1)\n{\n Name (_HID, \"PNPFFFF\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F800000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x55}\n PinFunction(Exclusive, PullDefault, 0x5,\n\"\\\\_SB.GPI0\", 0, ResourceConsumer, ) {2, 3}\n // Configure 10k Pull up for I2C SDA/SCL pins\n PinConfig(Exclusive, 0x01, 10000, \"\\\\_SB.GPI0\", 0, ResourceConsumer, ) {2, 3}\n })\n Return(RBUF)\n } }\n//\n// Description: Physical display panel //\nDevice (SDIO)\n{\n Name (_HID, \"PNPFFFD\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F900000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x57}\n GpioIo(Shared, PullDefault, 0, 0, IoRestrictionNone,\n\"\\\\_SB.GPI0\",) {2, 3}\n // Configure 20k Pull down\n PinConfig(Exclusive, 0x02, 20000, \"\\\\_SB.GPI0\", 0,\nResourceConsumer, ) {2, 3}\n // Enable Schmitt-trigger\n PinConfig(Exclusive, 0x0D, 1, \"\\\\_SB.GPI0\", 0,\nResourceConsumer, ) {2, 3}\n // Set slew rate to custom value 3\n PinConfig(Exclusive, 0x0B, 3, \"\\\\_SB.GPI0\", 0, ResourceConsumer, ) {2, 3}\n })\n Return(RBUF)\n}\n}" - }, - { - "title": "PinFunction (Pin Function)", - "syntax": "Macro:\nPinFunction(Shared/Exclusive, PinPullConfiguration, FunctionNumber, ResourceSource,\nResourceSourceIndex, ResourceUsage, DescriptorName, VendorData) {Pin List}", - "arguments": "\u2022 Shared is an optional argument and can be one of Shared, Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinPullConfiguration can be one of PullDefault, PullUp, PullDown, PullNone or a vendorsupplied value in the range 128-255.\n\u2022 FunctionNumber is a provider-specific integer that designates which function is being described.\n\u2022 ResourceSource is a string which uniquely identifies the GPIO controller referred to by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\n\u2022 ResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\n\u2022 ResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.\n\u2022 DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\n\u2022 VendorData is an optional argument that specifies a RawDataBuffer containing vendor-defined byte data to be decoded by the OS driver. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinList is a non-empty list of (zero-based) pin numbers on the ResourceSource that are described by this descriptor. The bit field name _PIN is automatically created to refer to this portion of the resource descriptor.", - "description": "The PinFunction macro evaluates to a buffer that contains a Pin Function resource descriptor, as described in this section. The macro is designed to be used inside of a Resource Template (Section 19.3.3).\nNote: PinFunction macro allows for maximum flexibility to define the desired function of each pin individually. It is the responsibility of the firmware writer to take into account any platform-level restrictions where pin function must be applied at a coarser granularity. Thus, if the platform design requires the functions for a set of pins to be configured as group, the firmware writer must ensure this is done in the corresponding PinFunction description by specifying all relevant pins in a single PinFunction. In the multi-pin scenario, the OSPM must honor the PinFunction requirements for all of the specified pins on an \u201call-or-nothing\u201d basis.\nNote: The Pin Function descriptor is intended for scenarios where non-GPIO functions are desired. For GPIO-based functionalities, the firmware should always specify the appropriate GpioIo or Gpioint descriptor.", - "example": "//\n// Description: GPIO //\nDevice (GPI0)\n{\n Name (_HID, \"PNPFFFE\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4FE00000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x54}\n })\n Return(RBUF)\n}\n//\n// Description: I2C controller 1 //\nDevice (I2C1)\n{\n Name (_HID, \"PNPFFFF\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F800000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x55}\n PinFunction(Exclusive, PullUp, 0x5, \"\\\\_SB.GPI0\", 0,\nResourceConsumer, ) {2, 3}\n })\n Return(RBUF)\n }\n}\n//\n// Description: I2C controller 2\n//\nDevice (I2C2)\n{\n Name (_HID, \"PNPFFFF\")\n Name (_UID, 0x1)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F900000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x56}\n PinFunction(Exclusive, PullUp, 0x0, 0x4,\n\"\\\\_SB.GPI0\", 0, ResourceConsumer, ) {2, 3}\n })\n Return(RBUF)\n}\n}\n//\n// Description: Physical display panel //\nDevice (DISP)\n{\n Name (_HID, \"PNPFFFD\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F900000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) {0x57}\n GpioIo(Shared, PullDefault, 0, 0, IoRestrictionNone,\n\"\\\\_SB.GPI0\",) {2, 3}\n })\n Return(RBUF)\n}\n}" - }, - { - "title": "PinGroup (Pin Group)", - "syntax": "Macro:\nPinGroup (ResourceLabel, ResourceUsage, DescriptorName, VendorData) { Pin List } Arguments\n\u2022 ResourceUsage is an optional argument and is assumed to be ResourceProducer for this revision.\n\u2022 ResourceLabel is an arbitrary, non-empty string that uniquely identifies this particular PinGroup resource from others within a resource template buffer. This label is used by resource consumers to refer to this resource.\n\u2022 DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\n\u2022 VendorData is an optional argument that specifies a RawDataBuffer containing vendor-defined byte data to be decoded by the OS driver. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinList is a non-empty list of (zero-based) pin numbers on the ResourceSource that are described by this descriptor. The bit field name _PIN is automatically created to refer to this portion of the resource descriptor.", - "arguments": "", - "description": "The PinGroup macro evaluates to a buffer that contains a Pin Group resource descriptor. The format of the Pin Group resource descriptor can be found in \"Pin Group Descriptor\" (Section 6.4.3.11). The macro is designed to be used inside of a Resource Template (Section 19.3.3).\nPinGroup resource descriptors must be declared within the scope of the pin controller device to which the pins belong.", - "example": "" - }, - { - "title": "PinGroupConfig (Pin Group Configuration)", - "syntax": "Macro:\nPinGroupConfig (Shared/Exclusive, PinConfigType, PinConfigValue, ResourceSource, ResourceSourceIndex, ResourceSourceLabel, ResourceUsage, DesriptorName, VendorData) Arguments:\n\u2022 Shared is an optional argument and can be either Shared or Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinConfigType can be one of the configuration types described below in Table 19-435. The bit field name _TYP is automatically created to refer to this portion of the resource descriptor.\n\u2022 PinConfigValue is one of the configurations values described below in Table 19-435. The bit field name _VAL is automatically created to refer to this portion of the resource descriptor. \u2022 ResourceSource is a string that uniquely identifies the GPIO controller which includes the PinGroup resource referenced by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\n\u2022 ResourceSourceLabel is a non-empty string argument that matches ResourceLabel of the PinGroup resource in the current resource template buffer of the GPIO controller referenced in ResourceSource.\n\u2022 DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\n\u2022 ResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\n\u2022 ResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.\n\u2022 VendorData is an optional argument that specifies a RawDataBuffer containing vendor-defined byte data to be decoded by the OS driver. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.\nTable 19-435 Pin Group Configuration Types and Values\nPin Configuration Type\nPin Configuration Value", - "arguments": "", - "description": "0x00 = Default\nN/A\nDefault configuration. No configuration is applied).\n0x01 = Bias Pull-Up\nPull up resistance, in\nOhms.\nThis means the pin is pulled up with a certain number of Ohms to an implicitly supplied VDD rail.\n0x02 = Bias Pull-down\nPull down resistance, in Ohms.\nThis means the pin is pulled down with a certain number of Ohms, toward the GND rail.\n0x03 = Bias Default\nN/A\nIf the silicon has a default biasing mode, reset the pin to this mode.\n0x04 = Bias Disable\nN/A\nAny software-selectable bias settings on the pin will be disabled.\n0x05 = Bias High Impedance\nN/A\nThis means that the pin is configured into a high impedance mode and essentially shut off from the outside world. It will not influence the signal state if a rail is connected to the pin, hence a good default mode.\nPin Configuration Type\nPin Configuration Value\n0x06 = Bias Bus Hold\nN/A\nThis will make the pin in a weak latch state where it weakly drives the last value on a tristate bus.\n0x07 = Drive Open Drain\nN/A\nThis will configure the pin into open drain (open collector) state.\n0x08 = Drive Open Source\nN/A\nThis will configure the pin into open source (open emitter) state.\n0x09 = Drive Push Pull\nN/A\nThis will configure the pin into explicit pushpull state. This is useful if the power-on default state is e.g. open drain or high impedance state.\n0x0A = Drive Strength\nDrive strength in milliamperes\nThis will set the output driver of the pin to supply a certain number of milliamperes, usually by activating several driver stages.\n0x0B = Slew Rate\nCustom format\nThis controls the slew rate of the pin, affecting speed but also sharpness of edges and thus noisiness on the board. The hardware-specific argument tells what slew rate to configure\n0x0C = Input Debounce\nDebounce time in microseconds.\nThis will enable debouncing (for e.g. key inputs) of the pin signal.\n0x0D = Input Schmitt Trigger\nEnabled = 1, Disabled = 0\nThis will enable Schmitt trigger support for the line.\n0x0E 0x7F = Reserved\nReserved\nReserved\n0x80 0xFF = Vendor defined values\nCustom base\nFrom this point, vendor and Hardwarespecific configurations are listed.\nThe PinGroupConfig macro evaluates to a buffer that contains a Pin Group Configuration resource descriptor. The format of the Pin Group Configuration resource descriptor can be found in \"Pin Group Configuration Descriptor\" (Section 6.4.3.13). The macro is designed to be used inside of a Resource Template (Section 19.3.3).", - "example": "//\n// Description: GPIO\n//\nDevice (GPI0)\n{\n Name (_HID, \"PNPFFFE\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4FE00000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x54}\n PinGroup(\u201cgroup1\u201d, ResourceProducer) {2, 3}\n })\n Return(RBUF)\n}\n//\n// Description: I2C controller 1 //\nDevice (I2C1)\n{\n Name (_HID, \"PNPFFFF\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F800000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x55}\n // Set function I2C1 for SDA/SCL pins \n PinGroupFunction(Exclusive, 0x5, \"\\\\_SB.GPI0, 0,\n\u201cgroup1\u201d, ResourceConsumer, )\n // Configure 10k Pull up for SDA/SCL pins\n PinGroupConfig(Exclusive, 0x01, 10000, \"\\\\_SB.GPI0 \", \n0, \u201cgroup1\u201d, ResourceConsumer, )\n })\n Return(RBUF)\n }\n}\n//\n// Description: I2C controller 2 //\nDevice (I2C2)\n{\n Name (_HID, \"PNPFFFF\")\n Name (_UID, 0x1)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F900000, 0x20)\n Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x56}\n // Set function I2C2 for SDA/SCL pins \n PinGroupFunction(Exclusive, 0x4, \"\\\\_SB.GPI0 \", 0,\n\u201cgroup1\u201d, ResourceConsumer, )\n // Configure 10k Pull up for SDA/SCL pins\n PinGroupConfig(Exclusive, 0x01, 10000, \"\\\\_SB.GPI0 \",\n0, \u201cgroup1\u201d, ResourceConsumer,)\n })\n Return(RBUF)\n}\n}\n//\n// Description: Physical display panel //\nDevice (DISP)\n{\n Name (_HID, \"PNPFFFD\")\n Name (_UID, 0x0)\n Method (_STA)\n {\n Return(0xf)\n }\n Method (_CRS, 0x0, NotSerialized)\n {\n Name (RBUF, ResourceTemplate()\n {\n Memory32Fixed(ReadWrite, 0x4F900000, 0x20) Interrupt(ResourceConsumer, Level, ActiveHigh,\nShared) {0x57}\n // Set function GPIO for pin group group1\n PinGroupFunction(Exclusive, 0x1, \"\\\\_SB.GPI0 \", 0,\n\u201cgroup1\u201d, ResourceConsumer, )\n // Configure 20k Pull down\n PinGroupConfig (Exclusive, 0x02, 20000, \"\\\\_SB.GPI0\n\", 0, \u201cgroup1\u201d, ResourceConsumer, )\n //Enable Schmitt-trigger\n PinGroupConfig (Exclusive, 0x0D, 1, \"\\\\_SB.GPI0 \", 0,\n\u201cgroup1\u201d, ResourceConsumer, )\n //Set slew rate to custom value 3\n PinGroupConfig (Exclusive, 0x0B, 3, \"\\\\_SB.GPI0 \", 0,\n\u201cgroup1\u201d, ResourceConsumer, )\n })\n Return(RBUF)}\n}\n}" - }, - { - "title": "PinGroupFunction (Pin Group Function)", - "syntax": "Macro:\nPinGroupFunction (Shared/Exclusive, FunctionNumber, ResourceSource, ResourceSourceIndex, ResourceSourceLabel, ResourceUsage, DescriptorName, VendorData) Arguments\n\u2022 Shared is an optional argument and can be one of Shared, Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\n\u2022 FunctionNumber is a provider-specific integer which designates which function is being described. The bit field name _FUN is automatically created to refere to this portion of the resource descriptor.\n\u2022 ResourceSource is a string that uniquely identifies the GPIO controller which includes the PinGroup resource referenced by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\n\u2022 ResourceSourceLabel is a non-empty string argument that matches ResourceLabel of a PinGroup resource in the current resource template buffer of the GPIO controller referenced in ResourceSource.\n\u2022 DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\n\u2022 ResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\n\u2022 ResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.\n\u2022 VendorData is an optional argument that specifies a RawDataBuffer containing vendor-defined byte data to be decoded by the OS driver. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.", - "arguments": "", - "description": "The PinGroupFunction macro evaluates to a buffer that contains a Pin Function resource descriptor. The format of the Pin Function resource descriptor can be found in \u201cPin Function Descriptor\u201d on page 460. The macro is designed to be used inside of an ASL Resource Template (Section 19.3.3).", - "example": "" - }, - { - "title": "PowerResource (Declare Power Resource)", - "syntax": "PowerResource (ResourceName, SystemLevel, ResourceOrder) {TermList}", - "arguments": "Declares a power resource named ResourceName. PowerResource opens a name scope.", - "description": "For a definition of the PowerResource term, see Section 7.2, \u201cDeclaring a Power Resource Object.\u201d\nThe power management object list is encoded as TermList, so that rather than describing a static power management object list, it is possible to describe a dynamic power management object list according to the system settings. See \"Section 5.4.2, Definition Block Loading.\"", - "example": "" - }, - { - "title": "Printf (Create and Store formatted string)", - "syntax": "Printf (FormatString, FormatArgs) => String", - "arguments": "Printf is a macro that converts the evaluated FormatString into a series of string Concatenate operations, storing the result in the Debug object.\nFormatString is a string literal which may contain one or more uses of the format specifier, %o, to indicate locations in the string where an object may be inserted. %o is the only format specifier supported since the resulting object is a string and type conversion is handled automatically by Concatenate.\nFormatArgs is a comma separated list of Named Objects, Locals, or Args that can be evaluated to a string. Each argument is added to the FormatString using the Concatenate operation at the location specified by %o in order of appearance.", - "description": "The Printf macro converts a format string into a series of cascading string Concatenate operations, and stores the result in the Debug object", - "example": "The following ASL example uses Printf to write a formatted string with the values of Arg0, Arg1, Arg2, and Arg3 to the Debug Object.\n Printf (\"%o: Unexpected value for %o, %o at line %o\", Arg0, Arg1, Arg2, Arg3)\nThis Printf macro expression evaluates to the following ASL operation.\n Store (Concatenate (Concatenate (Concatenate (Concatenate\n (Concatenate (Concatenate (Concatenate (\"\", Arg0),\n \": Unexpected value for \"), Arg1), \", \"), Arg2),\n \" at line \"), Arg3), Debug)" - }, - { - "title": "Processor (Declare Processor)", - "syntax": "Processor (ProcessorName, ProcessorID, PBlockAddress, PblockLength) {TermList}", - "arguments": "Declares a named processor object named ProcessorName. Processor opens a name scope. Each processor is required to have a unique ProcessorID value that is unique from any other ProcessorID value.\nFor each processor in the system, the ACPI system firmware declares one processor object in the namespace anywhere within the \\_SB scope. For compatibility with operating systems implementing ACPI 1.0, the processor object may also be declared under the \\_PR scope. An ACPI-compatible namespace may define Processor objects in either the \\_SB or \\_PR scope but not both.\nPBlockAddress provides the system I/O address for the processors register block. Each processor can supply a different such address. PBlockLength is the length of the processor register block, in bytes and is either 0 (for no P_BLK) or 6. With one exception, all processors are required to have the same\nPBlockLength. The exception is that the boot processor can have a non-zero PBlockLength when all other processors have a zero PBlockLength. It is valid for every processor to have a PBlockLength of 0.", - "description": "The following block of ASL sample code shows a use of the Processor term.\n \n Processor (\n \\_PR.CPU0, // Namespace name\n 1,\n 0x120, // PBlk system IO address\n 6 // PBlkLen\n ) {ObjectList}\nThe TermList is an optional list that may contain an arbitrary number of ASL Objects. Processor-specific objects that may be included in the TermList include _PTC, _CST, _PCT, _PSS, _PPC, _PSD, _TSD, _CSD, _PDC, _TPC, _TSS, and _OSC. These processor-specific objects can only be specified when the processor object is declared within the \\_SB scope. For a full definition of these objects, see Section 8, \u201cProcessor Configuration and Control.\u201d\nThe optional processor object list is encoded as TermList, so that rather than describing a static processor object list, it is possible to describe a dynamic processor object list according to the system settings. See \"Section 5.4.2, Definition Block Loading.\"", - "example": "" - }, - { - "title": "QWordIO (QWord IO Resource Descriptor Macro)", - "syntax": "QWordIO (ResourceUsage, IsMinFixed, IsMaxFixed, Decode, ISARanges, AddressGranularity,\nAddressMinimum, AddressMaximum, AddressTranslation, RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName, TranslationType, TranslationDensity)", - "arguments": "ResourceUsage specifies whether the I/O range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nIsMinFixed specifies whether the minimum address of this I/O range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this I/O range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nDecode specifies whether or not the device decodes the I/O range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nISARanges specifies whether the I/O ranges specifies are limited to valid ISA I/O ranges (ISAOnly), valid non-ISA I/O ranges (NonISAOnly) or encompass the whole range without limitation (EntireRange). The 2bit field DescriptorName._RNG is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is NonISAOnly, \u20182\u2019 is ISAOnly and \u20180\u2019 is EntireRange.\nAddressGranularity evaluates to a 64-bit integer that specifies the power-of-two boundary (- 1) on which the I/O range must be aligned. The 64-bit field DescriptorName. _GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 64-bit integer that specifies the lowest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 64-bit integer that specifies the highest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 64-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 64-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 64-bit integer that specifies the total number of bytes decoded in the I/O range. The 64-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this I/O range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nTranslationType is an optional argument that specifies whether the resource type on the secondary side of the bus is different (TypeTranslation) from that on the primary side of the bus or the same\n(TypeStatic). If TypeTranslation is specified, then the primary side of the bus is Memory. If TypeStatic is specified, then the primary side of the bus is I/O. If nothing is specified, then TypeStatic is assumed. The 1-bit field DescriptorName. _TTP is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is TypeTranslation and \u20180\u2019 is TypeStatic. See _TTP (page 443) for more information\nTranslationDensity is an optional argument that specifies whether or not the translation from the primary to secondary bus is sparse (SparseTranslation) or dense (DenseTranslation). It is only used when TranslationType is TypeTranslation. If nothing is specified, then DenseTranslation is assumed. The 1-bit field DescriptorName. _TRS is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SparseTranslation and \u20180\u2019 is DenseTranslation. See _TRS (page 444) for more information.", - "description": "The QWordIO macro evaluates to a buffer which contains a 64-bit I/O resource descriptor, which describes a range of I/O addresses. The format of the 64-bit I/O resource descriptor can be found in QWord Address Space Descriptor (page 431). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "QWordMemory (QWord Memory Resource Descriptor Macro)", - "syntax": "QWordMemory (ResourceUsage, Decode, IsMinFixed, IsMaxFixed, Cacheable, ReadAndWrite, AddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, RangeLength,\nResourceSourceIndex, ResourceSource, DescriptorName, MemoryRangeType, TranslationType)", - "arguments": "ResourceUsage specifies whether the Memory range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nDecode specifies whether or not the device decodes the Memory range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nIsMinFixed specifies whether the minimum address of this Memory range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this Memory range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nCacheable specifies whether or not the memory region is cacheable (Cacheable), cacheable and writecombining (WriteCombining), cacheable and prefetchable (Prefetchable) or uncacheable\n(NonCacheable). If nothing is specified, then NonCacheable is assumed. The 2-bit field DescriptorName.\n_MEM is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is Cacheable, \u20182\u2019 is WriteCombining, \u20183\u2019 is Prefetchable and \u20180\u2019 is NonCacheable.\nReadAndWrite specifies whether or not the memory region is read-only (ReadOnly) or read/write (ReadWrite). If nothing is specified, then ReadWrite is assumed. The 1-bit field DescriptorName._RW is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is ReadWrite and \u20180\u2019 is ReadOnly.\nAddressGranularity evaluates to a 64-bit integer that specifies the power-of-two boundary (- 1) on which the Memory range must be aligned. The 64-bit field DescriptorName. _GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 64-bit integer that specifies the lowest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 64-bit integer that specifies the highest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 64-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 64-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 64-bit integer that specifies the total number of bytes decoded in the Memory range. The 64-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this Memory range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nMemoryRangeType is an optional argument that specifies the memory usage. The memory can be marked as normal (AddressRangeMemory), used as ACPI NVS space (AddressRangeNVS), used as ACPI reclaimable space (AddressRangeACPI) or as system reserved (AddressRangeReserved). If nothing is specified, then AddressRangeMemory is assumed. The 2-bit field DescriptorName. _MTP is automatically created in order to refer to this portion of the resource descriptor, where \u20180\u2019 is AddressRangeMemory, \u20181\u2019 is AddressRangeReserved, \u20182\u2019 is AddressRangeACPI and \u20183\u2019 is AddressRangeNVS.\nTranslationType is an optional argument that specifies whether the resource type on the secondary side of the bus is different (TypeTranslation) from that on the primary side of the bus or the same (TypeStatic). If TypeTranslation is specified, then the primary side of the bus is I/O. If TypeStatic is specified, then the primary side of the bus is Memory. If nothing is specified, then TypeStatic is assumed. The 1-bit field DescriptorName. _TTP is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is TypeTranslation and \u20180\u2019 is TypeStatic. See _TTP (page 443) for more information.", - "description": "The QWordMemory macro evaluates to a buffer which contains a 64-bit memory resource descriptor, which describes a range of memory addresses. The format of the 64-bit memory resource descriptor can be found in \u201cQWord Address Space Descriptor \u201d (page 431). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "QWordSpace (QWord Space Resource Descriptor Macro)", - "syntax": "QWordSpace (ResourceType, ResourceUsage, Decode, IsMinFixed, IsMaxFixed, TypeSpecificFlags,\nAddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, RangeLength,\nResourceSourceIndex, ResourceSource, DescriptorName)", - "arguments": "ResourceType evaluates to an 8-bit integer that specifies the type of this resource. Acceptable values are 0xC0 through 0xFF.\nResourceUsage specifies whether the Memory range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nDecode specifies whether or not the device decodes the Memory range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nIsMinFixed specifies whether the minimum address of this Memory range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this Memory range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nTypeSpecificFlags evaluates to an 8-bit integer. The flags are specific to the ResourceType.\nAddressGranularity evaluates to a 64-bit integer that specifies the power-of-two boundary (- 1) on which the Memory range must be aligned. The 64-bit field DescriptorName. _GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 64-bit integer that specifies the lowest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 64-bit integer that specifies the highest possible base address of the\nMemory range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 64-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 64-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 64-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 64-bit integer that specifies the total number of bytes decoded in the Memory range. The 64-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this Memory range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The QWordSpace macro evaluates to a buffer which contains a 64-bit Address Space resource descriptor, which describes a range of addresses. The format of the 64-bit AddressSpace descriptor can be found in \u201cQWord Address Space Descriptor \u201d (page 431). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "RawDataBuffer", - "syntax": "RawDataBuffer (RDBufferSize) {ByteList} => RawDataBuffer", - "arguments": "Declares a RawDataBuffer of size RDBufferSize and optional initial value of ByteList.", - "description": "The optional RDBufferSize parameter specifies the size of the buffer and must be a word constant. The initial value is specified in Initializer ByteList. If RDBufferSize is not specified, it defaults to the size of initializer. If the count is too small to hold the value specified by initializer, the initializer size is used.\nNote that a RawDataBuffer is not encoded as a Buffer (Opcode, Package length bytes, etc), but rather contains only the raw bytes specified.", - "example": "" - }, - { - "title": "RefOf (Create Object Reference)", - "syntax": "RefOf (Object) => ObjectReference", - "arguments": "Object can be any object type (for example, a package, a device object, and so on).", - "description": "Returns an object reference to Object. If the Object does not exist, the result of a RefOf operation is fatal. Use the CondRefOf term in cases where the Object might not exist.\nThe primary purpose of RefOf() is to allow an object to be passed to a method as an argument to the method without the object being evaluated at the time the method was loaded.", - "example": "" - }, - { - "title": "Register (Generic Register Resource Descriptor Macro)", - "syntax": "Register (AddressSpaceKeyword, RegisterBitWidth, RegisterBitOffset, RegisterAddress, AccessSize, DescriptorName)", - "arguments": "AddressSpaceKeyword specifies the address space where the register exists. The register can be one of the following:\n\u2022 I/O space (SystemIO)\n\u2022 System Memory (SystemMemory)\n\u2022 PCI configuration space (PCI_Config)\n\u2022 Embedded controller space (EmbeddedControl)\n\u2022 SMBus (SMBus)\n\u2022 CMOS (SystemCMOS)\n\u2022 PCI Bar target (PciBarTarget)\n\u2022 IPMI (IPMI)\n\u2022 General purpose I/O (GeneralPurposeIO) \u2022 Generic serial bus (GenericSerialBus)\n\u2022 Platform Communications Channel (PCC)\n\u2022 Fixed-feature hardware (FFixedHW)\nThe 8-bit field DescriptorName. _ASI is automatically created in order to refer to this portion of the resource descriptor. See the Address Space ID definition in Table 6-238 for more information, including a list of valid values and their meanings.\nRegisterBitWidth evaluates to an 8-bit integer that specifies the number of bits in the register. The 8-bit field DescriptorName. _RBW is automatically created in order to refer to this portion of the resource descriptor. See the _RBW definition in Table 6-238 for more information.\nRegisterBitOffset evaluates to an 8-bit integer that specifies the offset in bits from the start of the register indicated by RegisterAddress. The 8-bit field DescriptorName. _RBO is automatically created in order to refer to this portion of the resource descriptor. See the _RBO definition in Table 6-238 for more information.\nRegisterAddress evaluates to a 64-bit integer that specifies the register address. The 64-bit field DescriptorName. _ADR is automatically created in order to refer to this portion of the resource descriptor. See the _ADR definition in Table 6-238 for more information.\nAccessSize evaluates to an 8-bit integer that specifies the size of data values used when accessing the address space as follows:\n0 - Undefined (legacy)\n1 - Byte access\n2 - Word access\n3 - DWord access\n4 - QWord access\nThe 8-bit field DescriptorName. _ASZ is automatically created in order to refer to this portion of the resource descriptor. See the _ASZ definition in Table 6-238 for more information. For backwards compatibility, the AccesSize parameter is optional when invoking the Register macro. If the AccessSize parameter is not supplied then the AccessSize field will be set to zero. In this case, OSPM will assume the access size.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The Register macro evaluates to a buffer that contains a generic register resource descriptor. The format of the generic register resource descriptor can be found in Table 6-238. The macro is designed to be used inside of the ResourceTemplate (Section 19.6.117).", - "example": "" - }, - { - "title": "Release (Release a Mutex Synchronization Object)", - "syntax": "Release (SyncObject)", - "arguments": "SynchObject must be a mutex synchronization object.", - "description": "If the mutex object is owned by the current invocation, ownership for the Mutex is released once. It is fatal to release ownership on a Mutex unless it is currently owned. A Mutex must be totally released before an invocation completes.", - "example": "" - }, - { - "title": "Reset (Reset an Event Synchronization Object)", - "syntax": "Reset (SyncObject)", - "arguments": "SynchObject must be an Event synchronization object.", - "description": "This operator is used to reset an event synchronization object to a non-signaled state. See also the Wait and Signal function operator definitions.", - "example": "" - }, - { - "title": "ResourceTemplate (Resource To Buffer Conversion Macro)", - "syntax": "ResourceTemplate () {ResourceMacroList} => Buffer", - "arguments": "", - "description": "For a full definition of the ResourceTemplateTerm macro, see Section 19.3.3, \u201cASL Resource Templates\u201d.", - "example": "" - }, - { - "title": "Return (Return from Method Execution)", - "syntax": "Return\nReturn ()\nReturn (Arg)", - "arguments": "Arg is optional and can be any valid object or reference.", - "description": "Returns control to the invoking control method, optionally returning a copy of the object named in Arg. If no Arg object is specified, a Return(Zero) is generated by the ASL compiler.\nNote: In the absence of an explicit Return () statement, the return value to the caller is undefined.", - "example": "" - }, - { - "title": "Revision (Constant Revision Integer)", - "syntax": "Revision => Integer", - "arguments": "", - "description": "The Revision operator returns an Integer containing the current revision of the AML interpreter. Writes to this object are not allowed.", - "example": "" - }, - { - "title": "Scope (Open Named Scope)", - "syntax": "Scope (Location) {ObjectList}", - "arguments": "Opens and assigns a base namespace scope to a collection of objects. All object names defined within the scope are created relative to Location. Note that Location does not have to be below the surrounding scope, but can refer to any location within the namespace. The Scope term itself does not create objects, but only locates objects within the namespace; the actual objects are created by other ASL terms.", - "description": "The object referred to by Location must already exist in the namespace and be one of the following object types that has a namespace scope associated with it:\n\u2022 A predefined scope such as: \\ (root), \\_SB, \\GPE, \\_PR, \\_TZ, etc.\n\u2022 Device\n\u2022 Processor\n\u2022 Thermal Zone\n\u2022 Power Resource\nThe Scope term alters the current namespace location to the existing Location. This causes the defined objects within TermList to be created relative to this new location in the namespace.\nThe object list is encoded as TermList, so that rather than describing a static object list, it is possible to describe a dynamic object list according to the system settings. See \"Section 5.4.2, Definition Block Loading.\"\nNote: When creating secondary SSDTs, it is often required to use the Scope operator to change the namespace location in order create objects within some part of the namespace that has been defined by the main DSDT. Use the External operator to declare the scope location so that the ASL compiler will not issue an error for an undefined Location.", - "example": "The following example ASL code uses the Scope operator and creates several objects:\nScope (\\PCI0)\n{\n Name (X, 3)\n Scope (\\)\n {\n Method (RQ) {Return (0)}\n }\n Name (^Y, 4) }\nThe created objects are placed in the ACPI namespace as shown:\n\\PCI0.X\n\\RQ \\Y\nThis example shows the use of External in conjunction with Scope within an SSDT:\nDefinitionBlock (\"ssdt.aml\", \"SSDT\", 2, \"X\", \"Y\", 0x00000001)\n{\n External (\\_SB.PCI0, DeviceObj)\n Scope (\\_SB.PCI0)\n { }\n}" - }, - { - "title": "ShiftLeft (Integer Shift Left)", - "syntax": "ShiftLeft (Source, ShiftCount, Result) => Integer\nResult = Source << ShiftCount => Integer\nResult <<= ShiftCount => Integer", - "arguments": "Source and ShiftCount are evaluated as Integers.", - "description": "Source is shifted left with the least significant bit zeroed ShiftCount times. The result is optionally stored into Result.", - "example": "" - }, - { - "title": "ShiftRight (Integer Shift Right)", - "syntax": "ShiftRight (Source, ShiftCount, Result) => Integer\nResult = Source >> ShiftCount => Integer\nResult >>= ShiftCount => Integer", - "arguments": "Source and ShiftCount are evaluated as Integers.", - "description": "Source is shifted right with the most significant bit zeroed ShiftCount times. The result is optionally stored into Result.", - "example": "" - }, - { - "title": "Signal (Signal a Synchronization Event)", - "syntax": "Signal (SyncObject)", - "arguments": "SynchObject must be an Event synchronization object.", - "description": "The Event object is signaled once, allowing one invocation to acquire the event.", - "example": "" - }, - { - "title": "SizeOf (Get Data Object Size)", - "syntax": "SizeOf (ObjectName) => Integer", - "arguments": "ObjectName must be a buffer, string or package object.", - "description": "Returns the size of a buffer, string, or package data object.\nFor a buffer, it returns the size in bytes of the data. For a string, it returns the size in bytes of the string, not counting the trailing NULL. For a package, it returns the number of elements. For an object reference, the size of the referenced object is returned. Other data types cause a fatal run-time error.", - "example": "" - }, - { - "title": "Sleep (Milliseconds Sleep)", - "syntax": "Sleep (MilliSeconds)", - "arguments": "The Sleep term is used to implement long-term timing requirements. Execution is delayed for at least the required number of milliseconds.", - "description": "The implementation of Sleep is to round the request up to the closest sleep time supported by the OS and relinquish the processor.", - "example": "" - }, - { - "title": "SPISerialBusV2 (SPI Serial Bus Connection Resource Descriptor (Version 2) Macro)", - "syntax": "SPISerialBusV2 (DeviceSelection, DeviceSelectionPolarity, WireMode, DataBitLength, SlaveMode,\nConnectionSpeed, ClockPolarity, ClockPhase, ResourceSource, ResourceSourceIndex, ResourceUsage, DescriptorName, Shared, VendorData)", - "arguments": "DeviceSelection is the device selection value. This value may refer to a chip-select line, GPIO line or other line selection mechanism. _ADR is automatically created to refer to this portion of the resource descriptor.\nDeviceSelectionPolarity is an optional argument and can be either PolarityHigh or PolarityLow to indicate that the device is active. PolarityLow is the default. The bit field _DPL is automatically created to refer to this portion of the resource descriptor.\nWireMode is an optional argument and can be either ThreeWireMode or FourWireMode. FourWireMode is the default. The bit field name _MOD is automatically created to refer to this portion of the resource descriptor.\nDataBitLength is the size, in bits, of the smallest transfer unit for this connection. _LEN is automatically created to refer to this portion of the resource descriptor.\nSlaveMode is an optional argument and can be either ControllerInitiated or DeviceInitiated.\nControllerInitiated is the default. The bit field name _SLV is automatically created to refer to this portion of the resource descriptor.\nConnectionSpeed is the maximum connection speed supported by this connection, in hertz. The bit field name _SPE is automatically created to refer to this portion of the resource descriptor.\nClockPolarity can be either ClockPolarityLow or ClockPolarityHigh. _POL is automatically created to refer to this portion of the resource descriptor.\nClockPhase can be either ClockPhaseFirst or ClockPhaseSecond. _PHA is automatically created to refer to this portion of the resource descriptor.\nResourceSource is a string which uniquely identifies the SPI bus controller referred to by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\nResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\nResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nShared is an optional argument and can be either Shared or Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\nVendorData is an optional argument that specifies an object to be decoded by the OS driver. It is a RawDataBuffer. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.", - "description": "The SPISerialBusV2 macro evaluates to a buffer that contains a SPI Serial Bus resource descriptor (Version 2). The macro is designed to be used inside of a ResourceTemplate (see Section 19.3.3).", - "example": "" - }, - { - "title": "Stall (Stall for a Short Time)", - "syntax": "Stall (MicroSeconds)", - "arguments": "The Stall term is used to implement short-term timing requirements. Execution is delayed for at least the required number of microseconds.", - "description": "The implementation of Stall is OS-specific, but must not relinquish control of the processor. Because of this, delays longer than 100 microseconds must use Sleep instead of Stall.", - "example": "" - }, - { - "title": "StartDependentFn (Start Dependent Function Resource Descriptor", - "syntax": "StartDependentFn (CompatibilityPriority, PerformancePriority) {ResourceList}", - "arguments": "CompatibilityPriority indicates the relative compatibility of the configuration specified by ResourceList relative to the PC/AT. 0 = Good, 1 = Acceptable, 2 = Sub-optimal.\nPerformancePriority indicates the relative performance of the configuration specified by ResourceList relative to the other configurations. 0 = Good, 1 = Acceptable, 2 = Sub-optimal.\nResourceList is a list of resources descriptors which must be selected together for this configuration.", - "description": "The StartDependentFn macro evaluates to a buffer which contains a start dependent function resource descriptor, which describes a group of resources which must be selected together. Each subsequent StartDependentFn or StartDependentFnNoPri resource descriptor introduces a new choice of resources for configuring the device, with the last choice terminated with an EndDependentFn resource descriptor. The format of the start dependent function resource descriptor can be found in \u201cStart Dependent Functions Descriptor\u201d (page 420). This macro generates the two-byte form of the resource descriptor. The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "StartDependentFnNoPri (Start Dependent Function Resource Descriptor Macro)", - "syntax": "StartDependentFnNoPri () {ResourceList}", - "arguments": "", - "description": "The StartDependentFnNoPri macro evaluates to a buffer which contains a start dependent function resource descriptor, which describes a group of resources which must be selected together. Each subsequent StartDependentFn or StartDependentFnNoPri resource descriptor introduces a new choice of resources for configuring the device, with the last choice terminated with an EndDependentFn resource descriptor. The format of the start dependent function resource descriptor can be found in \u201cStart Dependent Functions Descriptor\u201d (page 421). This macro generates the one-byte form of the resource descriptor. The macro is designed to be used inside of a ResourceTemplate (page 1033).\nThis is similar to StartDependentFn (page 1038) with both CompatibilityPriority and PerformancePriority set to 1, but is one byte shorter.", - "example": "" - }, - { - "title": "Store (Store an Object)", - "syntax": "Store (Source, Destination) => DataRefObject\nDestination = Source => DataRefObject", - "arguments": "This operation evaluates Source, converts it to the data type of Destination, and writes the result into\nDestination. For information on automatic data-type conversion, see Section 19.3.5, \u201cASL Data Types.\u201d", - "description": "Stores to OperationRegion Field data types may relinquish the processor depending on the address space.\nAll stores (of any type) to the constant Zero, constant One, or constant Ones object are not allowed. Stores to read-only objects are fatal. The execution result of the operation depends on the type of Destination. For any type other than an operation region field, the execution result is the same as the data written to Destination. For operation region fields with an AccessType of ByteAcc, WordAcc,\nDWordAcc, QWordAcc or AnyAcc, the execution result is the same as the data written to Destination as in the normal case, but when the AccessType is BufferAcc, the operation region handler may modify the data when it is written to the Destination so that the execution result contains modified data.", - "example": "The following example creates the name CNT that references an integer data object with the value 5 and then stores CNT to Local0. After the Store operation, Local0 is an integer object with the value 5.\nName (CNT, 5)\nStore (CNT, Local0)" - }, - { - "title": "Subtract (Integer Subtract)", - "syntax": "Subtract (Minuend, Subtrahend, Result) => Integer\nResult = Minuend - Subtrahend => Integer\nResult -= Subtrahend => Integer", - "arguments": "Minuend and Subtrahend are evaluated as Integers.", - "description": "Subtrahend is subtracted from Minuend, and the result is optionally stored into Result. Underflow conditions are ignored and the result simply loses the most significant bits.", - "example": "" - }, - { - "title": "Switch (Select Code To Execute Based On Expression)", - "syntax": "Switch (Expression) {CaseTermList}", - "arguments": "Expression is an ASL expression that evaluates to an Integer, String or Buffer.", - "description": "The Switch, Case and Default statements help simplify the creation of conditional and branching code. The Switch statement transfers control to a statement within the enclosed body of executable ASL code\nIf the Case Value is an Integer, Buffer or String, then control passes to the statement that matches the value of Switch (Expression). If the Case value is a Package, then control passes if any member of the package matches the Switch (Value) The Switch CaseTermList can include any number of Case instances, but no two Case Values (or members of a Value, if Value is a Package) within the same Switch statement can have the same value.\nExecution of the statement body begins at the selected TermList and proceeds until the TermList end of body or until a Break or Continue statement transfers control out of the body.\nThe Default statement is executed if no Case Value matches the value of Switch (expression). If the Default statement is omitted, and no Case match is found, none of the statements in the Switch body are executed. There can be at most one Default statement. The Default statement can appear anywhere in the body of the Switch statement.\nA Case or Default term can only appear inside a Switch statement. Switch statements can be nested. (Compatibility Note) The Switch, Case, and Default terms were first introduced in ACPI 2.0. However, their implementation is backward compatible with ACPI 1.0 AML interpreters.", - "example": "Use of the Switch statement usually looks something like this:\nSwitch (expression)\n{\n Case (value) {\n Statements executed if Lequal (expression, value)\n }\n Case (Package () {value, value, value}) {\n Statements executed if Lequal (expression, any value in package)\n }\n Default {\n Statements executed if expression does not equal any case constant-expression\n}\n}\nNote: (Compiler Note) The following example demonstrates how the Switch statement should be translated into ACPI 1.0-compatible AML:\nSwitch (Add (ABCD( ),1)\n{\n Case (1) {\n \u2026statements1\u2026\n }\n Case (Package () {4,5,6}) {\n \u2026statements2\u2026\n }\n Default {\n \u2026statements3\u2026\n }\n}\nis translated as:\nName (_T_I, 0) // Create Integer temporary variable for result While (One)\n{\n Store (Add (ABCD (), 1), _T_I)\n If (LEqual (_T_I, 1)) {\n \u2026statements1\u2026\n }\n Else {\n If (LNotEqual (Match (Package () {4, 5, 6}, MEQ, _T_I, MTR, 0, 0), Ones)) {\n \u2026statements2\u2026\n }\n Else {\n \u2026statements3\u2026\n }\n Break }\nThe While (One) is emitted to enable the use of Break and Continue within the Switch statement. Temporary names emitted by the ASL compiler should appear at the top level of the method, since the Switch statement could appear within a loop and thus attempt to create the name more than once.\nNote: If the ASL compiler is unable to determine the type of the expression, then it will generate a warning and assume a type of Integer. The warning will indicate that the code should use one of the type conversion operators (Such as ToInteger, ToBuffer, ToDecimalString or ToHexString). Caution: Some of these operators are defined starting with ACPI 2.0 and as such may not be supported by ACPI 1.0b compatible interpreters.\nFor example:\nSwitch (ABCD ()) // Cannot determine the type because methods can return anything.\n{\n \u2026case statements\u2026\n}\nwill generate a warning and the following code:\nName (_T_I, 0)\nStore (ABCD (), _T_I)\nTo remove the warning, the code should be:\nSwitch (ToInteger (ABCD ()))\n{\n \u2026case statements\u2026\n}" - }, - { - "title": "ThermalZone (Declare Thermal Zone)", - "syntax": "ThermalZone (ThermalZoneName) {TermList}", - "arguments": "Declares a Thermal Zone object named ThermalZoneName. ThermalZone opens a name scope.\nEach use of a ThermalZone term declares one thermal zone in the system. Each thermal zone in a system is required to have a unique ThermalZoneName.", - "description": "A thermal zone may be declared in the namespace anywhere within the \\_SB scope. For compatibility with operating systems implementing ACPI 1.0, a thermal zone may also be declared under the \\_TZ scope. An ACPI-compatible namespace may define Thermal Zone objects in either the \\_SB or \\_TZ scope but not both.\nFor example ASL code that uses a ThermalZone statement, see Section 11, \u201cThermal Management.\u201d\nThe thermal object list is encoded as TermList, so that rather than describing a static thermal object list, it is possible to describe a dynamic thermal object list according to the system settings. See \"Section 5.4.2, Definition Block Loading.\"", - "example": "" - }, - { - "title": "Timer (Get 64-Bit Timer Value)", - "syntax": "Timer => Integer", - "arguments": "", - "description": "The timer opcode returns a monotonically increasing value that can be used by ACPI methods to measure time passing, this enables speed optimization by allowing AML code to mark the passage of time independent of OS ACPI interpreter implementation.\nThe Sleep opcode can only indicate waiting for longer than the time specified.\nThe value resulting from this opcode is 64 bits. It is monotonically increasing, but it is not guaranteed that every result will be unique, i.e. two subsequent instructions may return the same value. The only guarantee is that each subsequent evaluation will be greater-than or equal to the previous ones.\nThe period of this timer is 100 nanoseconds. While the underlying hardware may not support this granularity, the interpreter will do the conversion from the actual timer hardware frequency into 100 nanosecond units.\nUsers of this opcode should realize that a value returned only represents the time at which the opcode itself executed. There is no guarantee that the next opcode in the instruction stream will execute in any particular time bound.\nThe OSPM can implement this using the ACPI Timer and keep track of overrun. Other implementations are possible. This provides abstraction away from chipset differences\nNote: (Compatibility Note) New for ACPI 3.0", - "example": "" - }, - { - "title": "ToBCD (Convert Integer to BCD)", - "syntax": "ToBCD (Value, Result) => Integer", - "arguments": "Value is evaluated as an integer", - "description": "The ToBCD operator is used to convert Value from a numeric (Integer) format to a BCD format and optionally store the numeric value into Result.", - "example": "" - }, - { - "title": "ToBuffer (Convert Data to Buffer)", - "syntax": "ToBuffer (Data, Result) => Buffer", - "arguments": "Data must be an Integer, String, or Buffer data type.", - "description": "Data is converted to buffer type and the result is optionally stored into Result. If Data is an integer, it is converted into n bytes of buffer (where n is 4 if the definition block has defined integers as 32 bits or 8 if the definition block has defined integers as 64 bits as indicated by the Definition Block table header\u2019s Revision field), taking the least significant byte of integer as the first byte of buffer. If Data is a buffer, no conversion is performed. If Data is a string, each ASCII string character is copied to one buffer byte, including the string null terminator. A null (zero-length) string will be converted to a zero-length buffer.", - "example": "" - }, - { - "title": "ToDecimalString (Convert Data to Decimal String)", - "syntax": "ToDecimalString (Data, Result) => String", - "arguments": "Data must be an Integer, String, or Buffer data type.", - "description": "Data is converted to a decimal string, and the result is optionally stored into Result. If Data is already a string, no action is performed. If Data is a buffer, it is converted to a string of decimal values separated by commas. (Each byte of the buffer is converted to a single decimal value.) A zero-length buffer will be converted to a null (zero-length) string.", - "example": "" - }, - { - "title": "ToHexString (Convert Data to Hexadecimal String)", - "syntax": "ToHexString (Data, Result) => String", - "arguments": "Data must be an Integer, String, or Buffer data type.", - "description": "Data is converted to a hexadecimal string, and the result is optionally stored into Result. If Data is already a string, no action is performed. If Data is a buffer, it is converted to a string of hexadecimal values separated by commas. A zero-length buffer will be converted to a null (zero-length) string.", - "example": "" - }, - { - "title": "ToInteger (Convert Data to Integer)", - "syntax": "ToInteger (Data, Result) => Integer", - "arguments": "Data must be an Integer, String, or Buffer data type.", - "description": "Data is converted to integer type and the result is optionally stored into Result. If Data is a string, it must be either a decimal or hexadecimal numeric string (in other words, prefixed by \u201c0x\u201d) and the value must not exceed the maximum of an integer value. If the value is exceeding the maximum, the result of the conversion is unpredictable. A null (zero-length) string is illegal. If Data is a Buffer, the first 8 bytes of the buffer are converted to an integer, taking the first byte as the least significant byte of the integer. A zerolength buffer is illegal. If Data is an integer, no action is performed.", - "example": "" - }, - { - "title": "ToPLD (Creates a _PLD Buffer Object)", - "syntax": "ToPLD (PLDKeywordList) => _PLD Buffer Object", - "arguments": "PLDKeywordList is a list of PLDKeyword types that describe elements of a Physical Layer Description (_PLD) buffer that can be assigned values. The table below shows the available PLDKeyword types and their assignable types. Refer to the _PLD section for a description of the _PLD method object.\nTable 19-436 PLD Keywords and Assignment Types\nPLDKeyword\nAssignment Type\nPLD_Revision\nInteger\nPLD_IgnoreColor\nInteger\nPLD_Red\nInteger\nPLD_Green\nInteger\nPLD_Blue\nInteger\nPLD_Width\nInteger\nPLD_Height\nInteger\nPLD_UserVisible\nInteger\nPLD_Dock\nInteger\nPLD_Lid\nInteger\nPLD_Panel\nInteger or String\nPLD_VerticalPosition\nInteger or String\nPLD_HorizontalPosition\nInteger or String\nPLD_Shape\nInteger or String\nPLD_GroupOrientation\nInteger\nPLD_GroupToken\nInteger\nPLD_GroupPosition\nInteger\nPLD_Bay\nInteger\nPLD_Ejectable\nInteger\nPLD_EjectRequired\nInteger\nPLD_CabinetNumber\nInteger\nPLD_CardCageNumber\nInteger\nPLD_Reference\nInteger\nPLD_Rotation\nInteger\nPLDKeyword\nAssignment Type\nPLD_Order\nInteger\nPLD_VeriticalOffset\nInteger\nPLD_HorizontalOffset\nInteger\nA subset of PLDKeyword types can be assigned string values for improved readability. Those types and their assignable values are shown in the table below.\nTable 19-437 PLD Keywords and assignable String Values\nPLDKeyword\nAssignable String Values\nPLD_Panel\n\u201cTOP\u201d, \u201cBOTTOM\u201d,\u201dLEFT\u201d, \u201cRIGHT\u201d,\u201dFRONT\u201d,\u201dBACK\u201d,\u201dUNKNOWN\u201d\nPLD_VerticalPosition\n\u201cUPPER\u201d,\u201dCENTER\u201d,\u201dLOWER\u201d\nPLD_HorizontalPosition\n\u201cLEFT\u201d,\u201dCENTER\u201d,\u201dRIGHT\u201d\nPLD_Shape\n\u201cROUND\u201d,\u201dOVAL\u201d,\u201dSQUARE\u201d,\n\u201cVERTICALRECTANGLE\u201d,\n\u201cHORIZONTALRECTANGLE\u201d,\n\u201cVERTICALTRAPEZOID\u201d,\n\u201cHORIZONTALTRAPEZOID\u201d,\n\u201cUNKNOWN\u201d", - "description": "The ToPLD macro converts a list of PLDKeyword types into a _PLD buffer object.", - "example": "The following ASL shows an example using ToPLDto construct a _PLD buffer/package object.\nName (_PLD, Package (0x01) // _PLD: Physical Location of Device\n {\n ToPLD (\n PLD_Revision = 0x2,\n PLD_IgnoreColor = 0x1,\n PLD_Red = 0x37,\n PLD_Green = 0x44,\n PLD_Blue = 0xFF, PLD_Width = 0x4,\n PLD_Height = 0x19,\n PLD_UserVisible = 0x1,\n PLD_Dock = 0x0,\n PLD_Lid = 0x1,\n PLD_Panel = \"TOP\",\n PLD_VerticalPosition = \"CENTER\",\n PLD_HorizontalPosition = \"RIGHT\",\n PLD_Shape = \"VERTICALRECTANGLE\",\n PLD_GroupOrientation = 0x1,\n PLD_GroupToken = 0xA,\n PLD_GroupPosition = 0x21,\n PLD_Bay = 0x1,\n PLD_Ejectable = 0x0,\n PLD_EjectRequired = 0x1,\n PLD_CabinetNumber = 0x1E,\n PLD_CardCageNumber = 0x17,\n PLD_Reference = 0x0,\n PLD_Rotation = 0x7,\n PLD_Order = 0x3,\n PLD_VerticalOffset = 0x141,\n PLD_HorizontalOffset = 0x2C) })" - }, - { - "title": "ToString (Convert Buffer To String)", - "syntax": "ToString (Source, Length, Result) => String", - "arguments": "Source is evaluated as a buffer. Length is evaluated as an integer data type.", - "description": "Starting with the first byte, the contents of the buffer are copied into the string until the number of characters specified by Length is reached or a null (0) character is found. If Length is not specified or is Ones, then the contents of the buffer are copied until a null (0) character is found. If the source buffer has a length of zero, a zero length (null terminator only) string will be created. The result is copied into the Result.", - "example": "" - }, - { - "title": "ToUUID (Convert String to UUID Macro)", - "syntax": "ToUUID (AsciiString) => Buffer", - "arguments": "AsciiString is evaluated as a String data type.", - "description": "This macro will convert an ASCII string to a 128-bit buffer. The string must have the following format:\naabbccdd-eeff-gghh-iijj-kkllmmnnoopp\nwhere aa pp are one byte hexadecimal numbers, made up of hexadecimal digits. The resulting buffer has the following format:\nTable 19-438 UUID Buffer Format\nString\nOffset In Buffer\naa\n3\nbb\n2\ncc\n1\ndd\n0\nee\n5\nff\n4\ngg\n7\nhh\n6\nii\n8\njj\n9\nkk\n10\nll\n11\nmm\n12\nnn\n13\noo\n14\npp\n15\nNote: (Compatibility Note) New for ACPI 3.0", - "example": "" - }, - { - "title": "UARTSerialBusV2 (UART Serial Bus Connection Resource Descriptor (Version 2) Macro)", - "syntax": "UARTSerialBusV2 (InitialBaudRate, BitsPerByte, StopBits, LinesInUse, IsBigEndian, Parity, FlowControl,\nReceiveBufferSize, TransmitBufferSize, ResourceSource, ResourceSourceIndex, ResourceUsage, DescriptorName, Shared, VendorData)", - "arguments": "InitialBaudRate evaluates to a 32-bit integer that specifies the default or initial connection speed in bytes per second that the device supports. The bit field _SPE is automatically created to refer to this portion of the resource descriptor.\nBitsPerByte is an optional argument that specifies whether five bits (DataBitsFive), six bits (DataBitsSix), seven bits (DataBitsSeven), eight bits (DataBitsEight) or nine bits (DataBitsNine) contain data during transfer of a single packet or character. DataBitsEight is the default. The bit field DescriptorName._LEN is automatically created to refer to this portion of the resource descriptor.\nStopBits is an optional argument that specifies whether there are two bits (StopBitsTwo), one and a half bits (StopBitsOnePlusHalf), one bit (StopBitsOne) or no bits (StopBitsZero) used to signal the end of a packet or character. StopBitsOne is the default. The bit field _STB is automatically created to refer to this portion of the resource descriptor.\nLinesInUse evaluates to an integer representing 8 1-bit flags representing the presence (\u20181\u2019) or absence (\u20180\u2019) of a particular line. The bit field _LIN is automatically created to refer to this portion of the resource descriptor.\nBit Mask\nUART Line\nBit 7 (0x80)\nRequest To Send (RTS)\nBit 6 (0x40)\nClear To Send (CTS)\nBit 5 (0x20)\nData Terminal Ready (DTR)\nBit 4 (0x10)\nData Set Ready (DSR)\nBit 3 (0x08)\nRing Indicator (RI)\nBit 2 (0x04)\nData Carrier Detect (DTD)\nBit 1 (0x02)\nReserved. Must be 0.\nBit 0 (0x01)\nReserved. Must be 0.\nIsBigEndian is an optional argument that specifies whether the device is expecting big endian (BigEndian) or little endian (LittleEndian) data formats. LittleEndian is the default. The bit field _END is automatically created to refer to this portion of the resource descriptor.\nParity is an optional argument that specifies whether the type of parity bits included after the data in a packet are to be interpreted as space parity (ParityTypeSpace), mark parity (ParityTypeMark), odd parity (ParityTypeOdd), even parity (ParityTypeEven) or no parity (ParityTypeNone). ParityTypeNone is the default. The bit field PAR is automatically created to refer to this portion of the resource descriptor.\nFlowControl is an optional argument that specifies whether there is hardware-based flow control\n(FlowControlHardware), software-based flow control (FlowControlXON) or no flow control\n(FlowControlNone) used when communicating with the device. FlowControlNone is the default. The bit field_FLC is automatically created to refer to this portion of the resource descriptor.\nReceiveBufferSize evaluates to a 16-bit integer that specifies the upper limit in bytes of the receive buffer that can be optimally utilized while communicating with this device. The bit field_RXL is automatically created to refer to this portion of the resource descriptor.\nTransmitBufferSize evaluates to a 16-bit integer that specifies the upper limit in bytes of the transmit buffer that can be optimally utilized while communicating with this device. The bit field _TXL is automatically created to refer to this portion of the resource descriptor.\nResourceSource is a string which uniquely identifies the UART bus controller referred to by this descriptor. ResourceSource can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search rules.\nResourceSourceIndex is an optional argument and is assumed to be 0 for this revision.\nResourceUsage is an optional argument and is assumed to be ResourceConsumer for this revision.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nShared is an optional argument and can be either Shared or Exclusive. If not specified, Exclusive is assumed. The bit field name _SHR is automatically created to refer to this portion of the resource descriptor.\nVendorData is an optional argument that specifies an object to be decoded by the OS driver. It is a RawDataBuffer. The bit field name _VEN is automatically created to refer to this portion of the resource descriptor.", - "description": "The UARTSerialBusV2 macro evaluates to a buffer that contains a UART Serial Bus resource descriptor (Version 2). The macro is designed to be used inside of a ResourceTemplate (seeSection 19.3.3 ).", - "example": "" - }, - { - "title": "Unicode (String To Unicode Conversion Macro)", - "syntax": "Unicode (String) => Buffer", - "arguments": "This macro will convert a string to a Unicode (UTF-16) string contained in a buffer. The format of the Unicode string is 16 bits per character, with a 16-bit null terminator.", - "description": "", - "example": "" - }, - { - "title": "VendorLong (Long Vendor Resource Descriptor)", - "syntax": "VendorLong (DescriptorName) {VendorByteList}", - "arguments": "DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer.\nVendorByteList evaluates to a comma-separated list of 8-bit integer constants, where each byte is added verbatim to the body of the VendorLong resource descriptor. A maximum of n bytes can be specified. UUID and UUID specific descriptor subtype are part of the VendorByteList.", - "description": "The VendorLong macro evaluates to a buffer which contains a vendor-defined resource descriptor. The format of the long form of the vendor-defined resource descriptor can be found in Vendor-Defined Descriptor (page 424). The macro is designed to be used inside of a ResourceTemplate (page 1033).\nThis is similar to VendorShort (page 1051), except that the number of allowed bytes in VendorByteList is 65,533 (instead of 7).", - "example": "" - }, - { - "title": "Unload (Unload Definition Block)[DEPRECATED]", - "syntax": "Unload (Handle)", - "arguments": "Handle is evaluated as a DDBHandle data type.", - "description": "Performs a run-time unload of a Definition Block that was loaded using a Load term or LoadTable term. Loading or unloading a Definition Block is a synchronous operation, and no control method execution occurs during the function. On completion of the Unload operation, the Definition Block has been unloaded (all the namespace objects created as a result of the corresponding Load operation will be removed from the namespace).", - "example": "" - }, - { - "title": "VendorShort (Short Vendor Resource Descriptor)", - "syntax": "VendorShort (DescriptorName) {VendorByteList}", - "arguments": "DescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer.", - "description": "The VendorShort macro evaluates to a buffer which contains a vendor-defined resource descriptor. The format of the short form of the vendor-defined resource descriptor can be found in \u201cVendor-Defined Descriptor\u201d (page 424). The macro is designed to be used inside of a ResourceTemplate (page 1033).\nThis is similar to VendorLong (page 1050), except that the number of allowed bytes in VendorByteList is 7 (instead of 65,533).", - "example": "" - }, - { - "title": "Wait (Wait for a Synchronization Event)", - "syntax": "Wait (SyncObject, TimeoutValue) => Boolean", - "arguments": "SynchObject must be an event synchronization object. TimeoutValue is evaluated as an Integer. The calling method blocks while waiting for the event to be signaled.", - "description": "The pending signal count is decremented. If there is no pending signal count, the processor is relinquished until a signal count is posted to the Event or until at least TimeoutValue milliseconds have elapsed.\nThis operation returns a non-zero value if a timeout occurred and a signal was not acquired. A TimeoutValue of 0xFFFF (or greater) indicates that there is no time out and the operation will wait indefinitely.", - "example": "" - }, - { - "title": "While (Conditional Loop)", - "syntax": "While (Predicate) {TermList}", - "arguments": "Predicate is evaluated as an integer.", - "description": "If the Predicate is non-zero, the list of terms in TermList is executed. The operation repeats until the Predicate evaluates to zero.\nNote: Creation of a named object more than once in a given scope is not allowed. As such, unconditionally creating named objects within a While loop must be avoided. A fatal error will be generated on the second iteration of the loop, during the attempt to create the same named object a second time.", - "example": "" - }, - { - "title": "WordBusNumber (Word Bus Number Resource Descriptor Macro)", - "syntax": "WordBusNumber (ResourceUsage, IsMinFixed, IsMaxFixed, Decode, AddressGranularity,\nAddressMinimum, AddressMaximum, AddressTranslation, RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName)", - "arguments": "ResourceUsage specifies whether the bus range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nIsMinFixed specifies whether the minimum address of this bus number range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field DescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this bus number range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field DescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nDecode specifies whether or not the device decodes the bus number range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nAddressGranularity evaluates to a 16-bit integer that specifies the power-of-two boundary (- 1) on which the bus number range must be aligned. The 16-bit field DescriptorName. _GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 16-bit integer that specifies the lowest possible bus number for the bus number range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 16-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 16-bit integer that specifies the highest possible bus number for the bus number range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 16-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 16-bit integer that specifies the offset to be added to a secondary bus bus number which results in the corresponding primary bus bus number. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 16-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 16-bit integer that specifies the total number of bus numbers decoded in the bus number range. The 16-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this I/O range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The WordBusNumber macro evaluates to a buffer which contains a 16-bit bus-number resource descriptor. The format of the 16-bit bus number resource descriptor can be found in \u201cWord Address Space Descriptor \u201d (page 437). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "WordIO (Word IO Resource Descriptor Macro)", - "syntax": "WordIO (ResourceUsage, IsMinFixed, IsMaxFixed, Decode, ISARanges, AddressGranularity,\nAddressMinimum, AddressMaximum, AddressTranslation, RangeLength, ResourceSourceIndex,\nResourceSource, DescriptorName, TranslationType, TranslationDensity)", - "arguments": "ResourceUsage specifies whether the I/O range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nIsMinFixed specifies whether the minimum address of this I/O range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field\nDescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this I/O range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field\nDescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nDecode specifies whether or not the device decodes the I/O range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nISARanges specifies whether the I/O ranges specifies are limited to valid ISA I/O ranges (ISAOnly), valid non-ISA I/O ranges (NonISAOnly) or encompass the whole range without limitation (EntireRange). The 2bit field DescriptorName._RNG is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is NonISAOnly, \u20182\u2019 is ISAOnly and \u20180\u2019 is EntireRange.\nAddressGranularity evaluates to a 16-bit integer that specifies the power-of-two boundary (- 1) on which the I/O range must be aligned. The 16-bit field DescriptorName. _GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 16-bit integer that specifies the lowest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 16-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 16-bit integer that specifies the highest possible base address of the I/O range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 16-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 16-bit integer that specifies the offset to be added to a secondary bus I/O address which results in the corresponding primary bus I/O address. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 16-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 16-bit integer that specifies the total number of bytes decoded in the I/O range. The 16-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this I/O range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.\nTranslationType is an optional argument that specifies whether the resource type on the secondary side of the bus is different (TypeTranslation) from that on the primary side of the bus or the same\n(TypeStatic). If TypeTranslation is specified, then the primary side of the bus is Memory. If TypeStatic is specified, then the primary side of the bus is I/O. If nothing is specified, then TypeStatic is assumed. The 1-bit field DescriptorName. _TTP is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is TypeTranslation and \u20180\u2019 is TypeStatic. See _TTP (page 444) for more information\nTranslationDensity is an optional argument that specifies whether or not the translation from the primary to secondary bus is sparse (SparseTranslation) or dense (DenseTranslation). It is only used when TranslationType is TypeTranslation. If nothing is specified, then DenseTranslation is assumed. The 1-bit field DescriptorName. _TRS is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SparseTranslation and \u20180\u2019 is DenseTranslation. See _TRS (page 444) for more information.", - "description": "The WordIO macro evaluates to a buffer which contains a 16-bit I/O range resource descriptor. The format of the 16-bit I/O range resource descriptor can be found in \u201cWord Address Space Descriptor \u201d (page 437). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "WordSpace (Word Space Resource Descriptor Macro) )", - "syntax": "WordSpace (ResourceType, ResourceUsage, Decode, IsMinFixed, IsMaxFixed, TypeSpecificFlags,\nAddressGranularity, AddressMinimum, AddressMaximum, AddressTranslation, RangeLength, ResourceSourceIndex, ResourceSource, DescriptorName)", - "arguments": "ResourceType evaluates to an 8-bit integer that specifies the type of this resource. Acceptable values are 0xC0 through 0xFF.\nResourceUsage specifies whether the bus range is consumed by this device (ResourceConsumer) or passed on to child devices (ResourceProducer). If nothing is specified, then ResourceConsumer is assumed.\nDecode specifies whether or not the device decodes the bus number range using positive (PosDecode) or subtractive (SubDecode) decode. If nothing is specified, then PosDecode is assumed. The 1-bit field DescriptorName. _DEC is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is SubDecode and \u20180\u2019 is PosDecode.\nIsMinFixed specifies whether the minimum address of this bus number range is fixed (MinFixed) or can be changed (MinNotFixed). If nothing is specified, then MinNotFixed is assumed. The 1-bit field DescriptorName. _MIF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MinFixed and \u20180\u2019 is MinNotFixed.\nIsMaxFixed specifies whether the maximum address of this bus number range is fixed (MaxFixed) or can be changed (MaxNotFixed). If nothing is specified, then MaxNotFixed is assumed. The 1-bit field DescriptorName. _MAF is automatically created to refer to this portion of the resource descriptor, where \u20181\u2019 is MaxFixed and \u20180\u2019 is MaxNotFixed.\nTypeSpecificFlags evaluates to an 8-bit integer. The flags are specific to the ResourceType.\nAddressGranularity evaluates to a 16-bit integer that specifies the power-of-two boundary (- 1) on which the bus number range must be aligned. The 16-bit field DescriptorName. _GRA is automatically created to refer to this portion of the resource descriptor.\nAddressMinimum evaluates to a 16-bit integer that specifies the lowest possible bus number for the bus number range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 16-bit field DescriptorName._MIN is automatically created to refer to this portion of the resource descriptor.\nAddressMaximum evaluates to a 16-bit integer that specifies the highest possible bus number for the bus number range. The value must have \u20180\u2019 in all bits where the corresponding bit in AddressGranularity is \u20181\u2019. For bridge devices which translate addresses, this is the address on the secondary bus. The 16-bit field DescriptorName._MAX is automatically created to refer to this portion of the resource descriptor.\nAddressTranslation evaluates to a 16-bit integer that specifies the offset to be added to a secondary bus bus number which results in the corresponding primary bus bus number. For all non-bridge devices or bridges which do not perform translation, this must be \u20180\u2019. The 16-bit field DescriptorName._TRA is automatically created to refer to this portion of the resource descriptor.\nRangeLength evaluates to a 16-bit integer that specifies the total number of bus numbers decoded in the bus number range. The 16-bit field DescriptorName. _LEN is automatically created to refer to this portion of the resource descriptor.\nResourceSourceIndex is an optional argument which evaluates to an 8-bit integer that specifies the resource descriptor within the object specified by ResourceSource. If this argument is specified, the ResourceSource argument must also be specified.\nResourceSource is an optional argument which evaluates to a string containing the path of a device which produces the pool of resources from which this I/O range is allocated. If this argument is specified, but the ResourceSourceIndex argument is not specified, a zero value is assumed.\nDescriptorName is an optional argument that specifies a name for an integer constant that will be created in the current scope that contains the offset of this resource descriptor within the current resource template buffer. The predefined descriptor field names may be appended to this name to access individual fields within the descriptor via the Buffer Field operators.", - "description": "The WordSpace macro evaluates to a buffer which contains a 16-bit Address Space resource descriptor. The format of the 16-bit Address Space resource descriptor can be found in \u201cWord Address Space\nDescriptor \u201d (page 437). The macro is designed to be used inside of a ResourceTemplate (page 1033).", - "example": "" - }, - { - "title": "XOr (Integer Bitwise Xor)", - "syntax": "XOr (Source1, Source2, Result) => Integer\nResult = Source1 ^ Source2 => Integer\nResult ^= Source => Integer", - "arguments": "Source1 and Source2 are evaluated as Integers.", - "description": "A bitwise XOR is performed and the result is optionally stored into Result.", - "example": "" - }, - { - "title": "_CDM (Clock Domain)", - "syntax": "", - "arguments": "", - "description": "This optional object conveys the processor clock domain to which a processor belongs. A processor clock domain is a unique identifier representing the hardware clock source providing the input clock for a given set of processors. This clock source drives software accessible internal counters, such as the Time Stamp Counter, in each processor. Processor counters in the same clock domain are driven by the same hardware clock source. In multi-processor platforms that utilize multiple clock domains, such counters may exhibit drift when compared against processor counters on different clock domains.\nThe _CDM object evaluates to an integer that identifies the device as belonging to a specific clock domain. OSPM assumes that two devices in the same clock domain are connected to the same hardware clock.", - "example": "" - }, - { - "title": "_CRS (Current Resource Settings)", - "syntax": "", - "arguments": "", - "description": "This required object evaluates to a byte stream that describes the system resources currently allocated to a device. Additionally, a bus device must supply the resources that it decodes and can assign to its children devices. If a device is disabled, then _CRS returns a valid resource template for the device, but the actual resource assignments in the return byte stream are ignored. If the device is disabled when _CRS is called, it must remain disabled.\nThe format of the data contained in a _CRS object follows the formats defined in Section 6.4 \u201cResource\nData Types for ACPI,\u201d a compatible extension of the formats specified in the PNPBIOS specification.[7] The resource data is provided as a series of data structures, with each of the resource data structures having a unique tag or identifier. The resource descriptor data structures specify the standard PC system resources, such as memory address ranges, I/O ports, interrupts, and DMA channels.", - "example": "" - }, - { - "title": "_DIS (Disable)", - "syntax": "", - "arguments": "", - "description": "This control method disables a device. When the device is disabled, it must not be decoding any hardware resources. Prior to running this control method, OSPM will have already put the device in the D3 state.\nWhen a device is disabled via the _DIS, the _STA control method for this device must return with the Disabled bit set.", - "example": "" - }, - { - "title": "_DMA (Direct Memory Access)", - "syntax": "", - "arguments": "", - "description": "This optional object returns a byte stream in the same format as a _CRS object. _DMA is only defined under devices that represent buses. It specifies the ranges the bus controller (bridge) decodes on the child-side of its interface. (This is analogous to the _CRS object, which describes the resources that the bus controller decodes on the parent-side of its interface.) Any ranges described in the resources of a _DMA object can be used by child devices for DMA or bus master transactions.\nThe _DMA object is only valid if a _CRS object is also defined. OSPM must re-evaluate the _DMA object after an _SRS object has been executed because the _DMA ranges resources may change depending on how the bridge has been configured.\nIf the _DMA object is not present for a bus device, the OS assumes that any address placed on a bus by a child device will be decoded either by a device on the bus or by the bus itself, (in other words, all address ranges can be used for DMA).\nFor example, if a platform implements a PCI bus that cannot access all of physical memory, it has a _DMA object under that PCI bus that describes the ranges of physical memory that can be accessed by devices on that bus.\nA _DMA object is not meant to describe any \u201cmap register\u201d hardware that is set up for each DMA transaction. It is meant only to describe the DMA properties of a bus that cannot be changed without reevaluating the _SRS method.", - "example": "" - }, - { - "title": "_DSD (Device Specific Data)", - "syntax": "", - "arguments": "", - "description": "This optional object is used to provide device drivers (via OSPM) with additional device properties and information. _DSD returns a variable-length package containing a list of Device Data Descriptor structures each consisting of a UUID (see Section 5.2.4) and a package (Data Structure). The UUID is all that is needed to define the Data Structure. The UUID itself may place a restriction based on _HID or the optional _CID, _CLS, _HRV, _SUB objects, or _HID and one of those optional objects. However, it also may not place such a restriction.\nNew UUIDs may be created by OEMs and IHVs or other interface or device governing bodies (e.g. the PCI SIG or the UEFI Forum), as long as the UUID is different from other published UUIDs.\nThe list of well-known UUIDs allocated for _DSD and the definition of data formats associated with them is available in an auxiliary document hosted on the UEFI Forum: http://www.uefi.org/acpi.", - "example": "" - }, - { - "title": "_FIX (Fixed Register Resource Provider)", - "syntax": "", - "arguments": "", - "description": "This optional object is used to provide a correlation between the fixed-hardware register blocks defined in the FADT and the devices in the ACPI namespace that implement these fixed-hardware registers. This object evaluates to a package of Plug and Play-compatible IDs (32-bit compressed EISA type IDs) that correlate to the fixed-hardware register blocks defined in the FADT. The device under which _FIX appears plays a role in the implementation of the fixed-hardware (for example, implements the hardware or decodes the hardware\u2019s address). _FIX conveys to OSPM whether a given device can be disabled, powered off, or should be treated specially by conveying its role in the implementation of the ACPI fixedhardware register interfaces. This object takes no arguments.\nThe _CRS object describes a device\u2019s resources. That _CRS object may contain a superset of the resources in the FADT, as the device may actually decode resources beyond what the FADT requires. Furthermore, in a machine that performs translation of resources within I/O bridges, the processor-relative resources in the FADT may not be the same as the bus-relative resources in the _CRS.", - "example": "" - }, - { - "title": "_GSB (Global System Interrupt Base)", - "syntax": "", - "arguments": "", - "description": "_GSB is an optional object that evaluates to an integer that corresponds to the Global System Interrupt\nBase for the corresponding I/O APIC device. The I/O APIC device may either be bus enumerated (e.g. as a PCI device) or enumerated in the namespace as described in Section 9.17,\u201dI/O APIC Device\u201d. Any I/O APIC device that either supports hot-plug or is not described in the MADT must contain a _GSB object.\nIf the I/O APIC device also contains a _MAT object, OSPM evaluates the _GSB object first before evaluating the _MAT object. By providing the Global System Interrupt Base of the I/O APIC, this object enables OSPM to process only the _MAT entries that correspond to the I/O APIC device. See\nSection 6.2.10, \u201c_MAT (Multiple APIC Table Entry)\u201d. Since _MAT is allowed to potentially return all the MADT entries for the entire platform, _GSB is needed in the I/O APIC device scope to enable OSPM to identify the entries that correspond to that device.\nIf an I/O APIC device is activated by a device-specific driver, the physical address used to access the I/O APIC will be exposed by the driver and cannot be determined from the _MAT object. In this case, OSPM cannot use the _MAT object to determine the Global System Interrupt Base corresponding to the I/O APIC device and hence requires the _GSB object.\nThe Global System Interrupt Base is a 64-bit value representing the corresponding I/OAPIC device as defined in Section 5.2.13, \u201cGlobal System Interrupts\u201d.", - "example": "" - }, - { - "title": "_HPP (Hot Plug Parameters)", - "syntax": "", - "arguments": "", - "description": "This optional object evaluates to a package containing the cache-line size, latency timer, SERR enable, and PERR enable values to be used when configuring a PCI device inserted into a hot-plug slot or for performing configuration of a PCI devices not configured by the platform boot firmware at system boot.\nThe object is placed under a PCI bus where this behavior is desired, such as a bus with hot-plug slots. _HPP provided settings apply to all child buses, until another _HPP object is encountered.", - "example": "" - }, - { - "title": "_HPX (Hot Plug Parameter Extensions)", - "syntax": "", - "arguments": "", - "description": "This optional object provides platform-specific information to the OSPM PCI driver component responsible for configuring PCI, PCI-X, or PCI Express Functions. The information conveyed applies to the entire hierarchy downward from the scope containing the _HPX object. If another _HPX object is encountered downstream, the settings conveyed by the lower-level object apply to that scope downward.\nOSPM uses the information returned by _HPX to determine how to configure PCI Functions that are hotplugged into the system, to configure Functions not configured by the platform firmware during initial system boot, and to configure Functions any time they lose configuration space settings (e.g. OSPM issues a Secondary Bus Reset/Function Level Reset or Downstream Port Containment is triggered). The _HPX object is placed within the scope of a PCI-compatible bus where this behavior is desired, such as a bus with hot-plug slots. It returns a single package that contains one or more sub-packages, each containing a single Setting Record. Each such Setting Record contains a Setting Type (INTEGER), a Revision number (INTEGER) and type/revision specific contents.\nThe format of data returned by the _HPX object is extensible. The Setting Type and Revision number determine the format of the Setting Record. OSPM ignores Setting Records of types that it does not understand. A Setting Record with higher Revision number supersedes that with lower revision number, however, the _HPX method can return both together, OSPM shall use the one with highest revision number that it understands. Type 3 records may have multiple records with the same revision or different revision (refer to the Revision field in Table 6-198. Out of all the Type 3 records, the OSPM shall determine the highest revision number that it understands and use all Type 3 records with that revision.\n_HPX may return multiple types or Record Settings (each setting in a single sub-package.) OSPM is responsible for detecting the type of Function and for applying the appropriate settings. OSPM is also responsible for detecting the device / port type of the PCI Express Function and applying the appropriate settings provided. For example, the Secondary Uncorrectable Error Severity and Secondary\nUncorrectable Error Mask settings of Type 2 record are only applicable to PCI Express to PCI-X/PCI Bridge whose device / port type is 1000b. Similarly, AER settings are only applicable to hot plug PCI Express devices that support the optional AER capability.", - "example": "" - }, - { - "title": "_MAT (Multiple APIC Table Entry)", - "syntax": "", - "arguments": "", - "description": "This optional object evaluates to a buffer returning data in the format of a series of Multiple APIC Description Table (MADT) APIC Structure entries. This object can appear under an I/O APIC or processor object definition as processors may contain Local APICs. Specific types of MADT entries are meaningful to\n(in other words, is processed by) OSPM when returned via the evaluation of this object as described in Table 5-45. Other entry types returned by the evaluation of _MAT are ignored by OSPM.\nWhen _MAT appears under a Processor object, OSPM uses the ACPI processor ID in the entries returned from the object\u2019s evaluation to identify the entries corresponding to either the ACPI processor ID of the Processor object or the value returned by the _UID object under a Processor device.", - "example": "" - }, - { - "title": "_OSC (Operating System Capabilities)", - "syntax": "", - "arguments": "", - "description": "This optional object is a control method that is used by OSPM to communicate to the platform the feature support or capabilities provided by a device\u2019s driver. This object is a child object of a device and may also exist in the \\_SB scope, where it can be used to convey platform wide OSPM capabilities. When supported, _OSC is invoked by OSPM immediately after placing the device in the D0 power state. Device specific objects are evaluated after _OSC invocation. This allows the values returned from other objects to be predicated on the OSPM feature support / capability information conveyed by _OSC. OSPM may evaluate _OSC multiple times to indicate changes in OSPM capability to the device but this may be precluded by specific device requirements. As such, _OSC usage descriptions in Section 9, \u201cACPI-Defined Devices and Device Specific Objects\u201d, or other governing specifications describe superseding device specific _OSC capabilities and / or preclusions.\n_OSC enables the platform to configure its ACPI namespace representation and object evaluations to match the capabilities of OSPM. This enables legacy operating system support for platforms with new features that make use of new namespace objects that if exposed would not be evaluated when running a legacy OS. _OSC provides the capability to transition the platform to native operating system support of new features and capabilities when available through dynamic namespace reconfiguration. _OSC also allows devices with Compatible IDs to provide superset functionality when controlled by their native (For example, _HID matched) driver as appropriate objects can be exposed accordingly as a result of OSPM\u2019s evaluation of _OSC.", - "example": "" - }, - { - "title": "_PRS (Possible Resource Settings)", - "syntax": "", - "arguments": "", - "description": "This optional object evaluates to a byte stream that describes the possible resource settings for the device. When describing a platform, specify a _PRS for all the configurable devices. Static (nonconfigurable) devices do not specify a _PRS object. The information in this package is used by OSPM to select a conflict-free resource allocation without user intervention. This method must not reference any operation regions that have not been declared available by a _REG method.\nThe format of the data in a _PRS object follows the same format as the _CRS object (for more information, see the _CRS object definition in Section 6.2.2, \u201c_CRS (Current Resource Settings)\u201d).\nIf the device is disabled when _PRS is called, it must remain disabled.", - "example": "" - }, - { - "title": "_PRT (PCI Routing Table)", - "syntax": "", - "arguments": "", - "description": "PCI interrupts are inherently non-hierarchical. PCI interrupt pins are wired to interrupt inputs of the interrupt controllers. The _PRT object provides a mapping from PCI interrupt pins to the interrupt inputs of the interrupt controllers. The _PRT object is required under all PCI root bridges. _PRT evaluates to a package that contains a list of packages, each of which describes the mapping of a PCI interrupt pin.\nAddress\nDWORD\nThe address of the device (uses the same format as _ADR).\nPin\nByte\nThe PCI pin number of the device (0\u2013INTA, 1\u2013INTB, 2\u2013INTC, 3\u2013INTD).\nSource\nNamePath\nOr\nByte\nName of the device that allocates the interrupt to which the above pin is connected. The name can be a fully qualified path, a relative path, or a simple name segment that utilizes the namespace search rules. Note: This field is a NamePath and not a String literal, meaning that it should not be surrounded by quotes. If this field is the integer constant Zero (or a Byte value of 0), then the interrupt is allocated from the global interrupt pool.\nSource Index\nDWORD\nIndex that indicates which resource descriptor in the resource template of the device pointed to in the Source field this interrupt is allocated from. If the Source field is the Byte value zero, then this field is the global system interrupt number to which the pin is connected.\nThere are two ways that _PRT can be used. Typically, the interrupt input that a given PCI interrupt is on is configurable. For example, a given PCI interrupt might be configured for either IRQ 10 or 11 on an 8259 interrupt controller. In this model, each interrupt is represented in the ACPI namespace as a PCI Interrupt Link Device.\nThese objects have _PRS, _CRS, _SRS, and _DIS control methods to allocate the interrupt. Then, OSPM handles the interrupts not as interrupt inputs on the interrupt controller, but as PCI interrupt pins. The driver looks up the device\u2019s pins in the _PRT to determine which device objects allocate the interrupts. To move the PCI interrupt to a different interrupt input on the interrupt controller, OSPM uses _PRS, _CRS, _SRS, and _DIS control methods for the PCI Interrupt Link Device.\nIn the second model, the PCI interrupts are hardwired to specific interrupt inputs on the interrupt controller and are not configurable. In this case, the Source field in _PRT does not reference a device, but instead contains the value zero, and the Source Index field contains the global system interrupt to which the PCI interrupt is hardwired.\n6.Example: Using _PRT to Describe PCI IRQ Routing\nThe following example describes two PCI slots and a PCI video chip. Notice that the interrupts on the two PCI slots are wired differently (barber-poled).\nScope(\\_SB) {\n Device(LNKA){\n Name(_HID, EISAID(\"PNP0C0F\")) // PCI interrupt link\n Name(_UID, 1)\n Name(_PRS, ResourceTemplate(){\n Interrupt(ResourceProducer,\u2026) {10,11} // IRQs 10,11\n })\n Method(_DIS) {\u2026}\n Method(_CRS) {\u2026}\n Method(_SRS, 1) {\u2026}\n }\n Device(LNKB){\n Name(_HID, EISAID(\"PNP0C0F\")) // PCI interrupt link\n Name(_UID, 2)\n Name(_PRS, ResourceTemplate(){\n Interrupt(ResourceProducer,\u2026) {11,12} // IRQs 11,12\n })\n Method(_DIS) {\u2026}\n Method(_CRS) {\u2026}\n Method(_SRS, 1) {\u2026}\n }\n Device(LNKC){\n Name(_HID, EISAID(\"PNP0C0F\")) // PCI interrupt link\n Name(_UID, 3)\n Name(_PRS, ResourceTemplate(){\n Interrupt(ResourceProducer,\u2026) {12,14} // IRQs 12,14\n })\n Method(_DIS) {\u2026}\n Method(_CRS) {\u2026}\n Method(_SRS, 1) {\u2026}\n }\n Device(LNKD){\n Name(_HID, EISAID(\"PNP0C0F\")) // PCI interrupt link\n Name(_UID, 4)\n Name(_PRS, ResourceTemplate(){\n Interrupt(ResourceProducer,\u2026) {10,15} // IRQs 10,15\n })\n Method(_DIS) {\u2026}\n Method(_CRS) {\u2026}\n Method(_SRS, 1) {\u2026}\n }\n Device(PCI0){\n \u2026\n Name(_PRT, Package{ // A fully qualified pathname can be used,\n // or a simple name segment utilizing the search rules.\n Package{0x0004FFFF, 0, \\_SB_.LNKA, 0}, // Slot 1, INTA\n Package{0x0004FFFF, 1, \\_SB_.LNKB, 0}, // Slot 1, INTB \n Package{0x0004FFFF, 2, \\_SB_.LNKC, 0}, // Slot 1, INTC Package{0x0004FFFF, 3, \\_SB_.LNKD, 0}, // Slot 1, INTD\n Package{0x0005FFFF, 0, LNKB, 0}, // Slot 2, INTA \n Package{0x0005FFFF, 1, LNKC, 0}, // Slot 2, INTB \n Package{0x0005FFFF, 2, LNKD, 0}, // Slot 2, INTC \n Package{0x0005FFFF, 3, LNKA, 0}, // Slot 2, INTD \n Package{0x0006FFFF, 0, LNKC, 0} // Video, INTA\n })\n }\n}", - "example": "" - }, - { - "title": "_PXM (Proximity)", - "syntax": "", - "arguments": "", - "description": "This optional object is used to describe proximity domain associations within a machine. _PXM evaluates to an integer that identifies a device as belonging to a Proximity Domain defined in the System Resource Affinity Table (SRAT). OSPM assumes that two devices in the same proximity domain are tightly coupled. OSPM could choose to optimize its behavior based on this. For example, in a system with four processors and six memory devices, there might be two separate proximity domains (0 and 1), each with two processors and three memory devices. In this case, the OS may decide to run some software threads on the processors in proximity domain 0 and others on the processors in proximity domain 1. Furthermore, for performance reasons, it could choose to allocate memory for those threads from the memory devices inside the proximity domain common to the processor and the memory device rather than from a memory device outside of the processor\u2019s proximity domain.\nChildren of a device belong to the same proximity domain as their parent unless they contain an overriding _PXM. Proximity domains do not imply any ejection relationships.\nOSPM shall make no assumptions about the proximity or nearness of different proximity domains. The difference between two integers representing separate proximity domains does not imply distance between the proximity domains (in other words, proximity domain 1 is not assumed to be closer to proximity domain 0 than proximity domain 6).\nIf the Local APIC ID / Local SAPIC ID / Local x2APIC ID or the GICC ACPI Processor UID of a dynamically added processor is not present in the System Resource Affinity Table (SRAT), a _PXM object must exist for the processor\u2019s device or one of its ancestors in the ACPI Namespace. See Section 5.2.16, \u201cSystem Resource Affinity Table (SRAT)\u201d and Section 6.2.14, \u201c_PXM (Proximity)\u201d for more information.", - "example": "" - }, - { - "title": "_SLI (System Locality Information)", - "syntax": "", - "arguments": "", - "description": "The System Locality Information Table (SLIT) table defined in Section 5.2.16.6, \u201cSystem Locality Distance Information Table (SLIT)\u201d provides relative distance information between all System Localities for use during OS initialization.\nThe value of each Entry[i,j] in the SLIT table, where i represents a row of a matrix and j represents a column of a matrix, indicates the relative distances from System Locality / Proximity Domain i to every other System Locality j in the system (including itself).\nThe i,j row and column values correlate to the value returned by the _PXM object in the ACPI namespace. See Section 6.2.14, \u201c_PXM (Proximity)\u201d for more information.\nDynamic runtime reconfiguration of the system may cause the distance between System Localities to change.\n_SLI is an optional object that enables the platform to provide the OS with updated relative System Locality distance information at runtime. _SLI provide OSPM with an update of the relative distance from System Locality i to all other System Localities in the system.\nHeader\n \n \n \n Signature\n4\n0\n\u2018SLIT\u2019.\n Length\n4\n4\n60\n Revision\n1\n8\n1\n Checksum\n1\n9\nEntire table must sum to zero.\n OEMID\n6\n10\nOEM ID.\n OEM Table ID\n8\n16\nFor the System Locality Information Table, the table ID is the manufacturer model ID.\n OEM Revision\n4\n24\nOEM revision of System Locality Information Table for supplied OEM Table ID.\n Creator ID\n4\n28\nVendor ID of utility that created the table. For the DSDT, RSDT, SSDT, and PSDT tables, this is the ID for the ASL Compiler.\n Creator Revision\n4\n32\nRevision of utility that created the table. For the DSDT, RSDT, SSDT, and PSDT tables, this is the revision for the ASL Compiler.\nNumber of System\nLocalities\n8\n36\n4\nEntry[0][0]\n1\n44\n10\nEntry[0][1]\n1\n45\n15\nEntry[0][2]\n1\n46\n20\nField\nByte\nLength\nByte Offset\nEntry[0][3]\n1\n47\n18\nEntry[1][0]\n1\n48\n15\nEntry[1][1]\n1\n49\n10\nEntry[1][2]\n1\n50\n16\nEntry[1][3]\n1\n51\n24\nEntry[2][0]\n1\n52\n20\nEntry[2][1]\n1\n53\n16\nEntry[2][2]\n1\n54\n10\nEntry[2][3]\n1\n55\n12\nEntry[3][0]\n1\n56\n18\nEntry[3][1]\n1\n57\n24\nEntry[3][2]\n1\n58\n12\nEntry[3][3]\n1\n59\n10\nIf a new node, \u201cNode 4\u201d, is added, then Table 6-204 represents the updated system\u2019s NUMA relative distances of proximity domains.\nTable 6-204 Example Relative Distances Between Proximity Domains - 5 Node\nProximity Domain\n0\n1\n2\n3\n4\n0\n10\n15\n20\n18\n17\n1\n15\n10\n16\n24\n21\n2\n20\n16\n10\n12\n14\n3\n18\n24\n12\n10\n23\n4\n17\n21\n14\n23\n10\nThe new node\u2019s _SLI object would evaluate to a buffer containing [17,21,14,23,10,17,21,14,23,10].\nNote: Some systems support interleave memory across the nodes. The SLIT representation of these systems is implementation specific.", - "example": "" - }, - { - "title": "_SRS (Set Resource Settings)", - "syntax": "", - "arguments": "", - "description": "This optional control method takes one byte stream argument that specifies a new resource allocation for a device. The resource descriptors in the byte stream argument must be specified exactly as listed in the _CRS byte stream meaning that the identical resource descriptors must appear in the identical order, resulting in a buffer of exactly the same length. Optimizations such as changing an IRQ descriptor to an IRQNoFlags descriptor (or vice-versa) must not be performed. Similarly, changing\nStartDependentFn to StartDependentFnNoPri is not allowed. A _CRS object can be used as a template to ensure that the descriptors are in the correct format. For more information, see the _CRS object definition.\nThe settings must take effect before the _SRS control method returns.\nThis method must not reference any operation regions that have not been declared available by a _REG method.\nIf the device is disabled, _SRS enables the device at the specified resources. _SRS is not used to disable a device; use the _DIS control method instead.", - "example": "" - }, - { - "title": "_CCA (Cache Coherency Attribute)", - "syntax": "", - "arguments": "", - "description": "The _CCA object returns whether or not a bus-master device supports hardware managed cache coherency. Expected values are 0 to indicate it is not supported, and 1 to indicate that it is supported. All other values are reserved.\nOn platforms for which existing default cache-coherency behavior of the OS is not adequate, _CCA enables the OS to adapt to the differences. If used, _CCA must be included under all bus-master-capable devices defined as children of \\_SB, to ensure that the operating system knows when it can rely on hardware managed cache coherency. The value of _CCA is inherited by all descendants of these devices, so it need not be repeated for their children devices and will be ignored by OSPM if it is provided there. This includes slave devices on a shared DMA controller; thus these DMA controllers must also be defined in the namespace under the System Bus and include a _CCA object.\nIf a device indicates it does not have hardware cache coherency support, then OSPM must use a software cache flushing algorithm to ensure stale or invalid data is not accessed from the caches.\n__CCA objects are only relevant for devices that can access CPU-visible memory, such as devices that are DMA capable. On ARM based systems, the _CCA object must be supplied all such devices. On Intel platforms, if the _CCA object is not supplied, the OSPM will assume the devices are hardware cache coherent.", - "example": "" - }, - { - "title": "_HMA (Heterogeneous Memory Attributes)", - "syntax": "", - "arguments": "", - "description": "The Heterogeneous Memory Attributes Table (HMAT) defined in Section provides Heterogeneous Memory Attributes. Dynamic runtime reconfiguration of the system may cause proximities domains or memory attributes to change. If the \u201cReservation Hint\u201d is set, new HMAT update shall not reset the \u201cReservation Hint\u201d unless the memory range is removed.\n_HMA is an optional object that enables the platform to provide the OS with updated Heterogeneous Memory Attributes information at runtime. _HMA provides OSPM with the latest HMAT in entirety overriding existing HMAT.\n_EDL\nObject that evaluates to a package of namespace references of device objects that depend on the device containing _EDL.\n_EJD\nObject that evaluates to the name of a device object on which a device depends. Whenever the named device is ejected, the dependent device must receive an ejection notification.\n_EJx\nControl method that ejects a device.\n_LCK\nControl method that locks or unlocks a device.\n_OST\nControl method invoked by OSPM to convey processing status to the platform.\n_RMV\nObject that indicates that the given device is removable.\n_STA\nControl method that returns a device\u2019s status.", - "example": "" - }, - { - "title": "_EDL (Eject Device List)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to a package of namespace references containing the names of device objects that depend on the device under which the _EDL object is declared. This is primarily used to support docking stations. Before the device under which the _EDL object is declared may be ejected, OSPM prepares the devices listed in the _EDL object for physical removal.", - "example": "" - }, - { - "title": "_EJD (Ejection Dependent Device)", - "syntax": "", - "arguments": "", - "description": "This object is used to specify the name of a device on which the device, under which this object is declared, is dependent. This object is primarily used to support docking stations. Before the device indicated by _EJD is ejected, OSPM will prepare the dependent device (in other words, the device under which this object is declared) for removal.", - "example": "" - }, - { - "title": "_EJx (Eject)", - "syntax": "", - "arguments": "", - "description": "These control methods are optional and are supplied for devices that support a software-controlled VCRstyle ejection mechanism or that require an action be performed such as isolation of power/data lines before the device can be removed from the system. To support warm (system is in a sleep state) and hot (system is in S0) removal, an _EJx control method is listed for each sleep state from which the device supports removal, where x is the sleeping state supported. For example, _EJ0 indicates the device supports hot removal; _EJ1\u2013EJ4 indicate the device supports warm removal.", - "example": "" - }, - { - "title": "_LCK (Lock)", - "syntax": "", - "arguments": "", - "description": "This control method is optional and is required only for a device that supports a software-controlled locking mechanism. When the OS invokes this control method, the associated device is to be locked or unlocked based upon the value of the argument that is passed. On a lock request, the control method must not complete until the device is completely locked.", - "example": "" - }, - { - "title": "_OST (OSPM Status Indication)", - "syntax": "", - "arguments": "", - "description": "This object is an optional control method that is invoked by OSPM to indicate processing status to the platform. During device ejection, device hot add, Error Disconnect Recover, or other event processing, OSPM may need to perform specific handshaking with the platform. OSPM may also need to indicate to the platform its inability to complete a requested operation; for example, when a user presses an ejection button for a device that is currently in use or is otherwise currently incapable of being ejected. In this case, the processing of the ACPI Eject Request notification by OSPM fails. OSPM may indicate this failure to the platform through the invocation of the _OST control method. As a result of the status notification indicating ejection failure, the platform may take certain action including reissuing the notification or perhaps turning on an appropriate indicator light to signal the failure to the user. Arguments: (3)\nArg0 An Integer containing the source event\nArg1 An Integer containing the status code Arg2 A Buffer containing status information\nReturn Value: None\nArgument Information:\nArg0 source_event: DWordConst\nIf the value of source_event is <= 0xFF, this argument is the ACPI notification value whose processing generated the status indication. This is the value that was passed into the Notify operator.\nIf the value of source_event is 0x100 or greater then the OSPM status indication is a result of an OSPM action as indicated in Table 6-206. For example, a value of 0x103 will be passed into _OST for this argument upon the failure of a user interface invoked device ejection.\nIf OSPM is unable to identify the originating notification value, OSPM invokes _OST with a value that contains all bits set (ones) for this parameter.\nArg1 Status Code: DWordConst. OSPM indicates a notification value specific status. See Table 6-207, Table 6-208, and Table 6-210 for status code descriptions.\nArg2 A buffer containing detailed OSPM-specific information about the status indication. This argument may be null.\nTable 6-206 OST Source Event Codes\nSource Event Code\n0-0xFF\nReserved for Notification Values\n0x100\nOperation System Shutdown Processing\n0x101-0x102\nReserved\n0x103\nEjection Processing\n0x104-0x1FF\nReserved\n0x200\nInsertion Processing\n0x201-0xFFFFFFFF\nReserved\nTable 6-207 General Processing Status Codes\nStatus Code\n0\nSuccess\n1\nNon-specific failure\n2\nUnrecognized Notify Code\n3-0x7F\nReserved\n0x80-0xFFFFFFFF\nNotification value specific status codes\nTable 6-208 Operating System Shutdown Processing (Source Events : 0x100) Status Codes\nStatus Code\n0x80\nOS Shutdown Request denied\n0x81\nOS Shutdown in progress\n0x82\nOS Shutdown completed\n0x83\nOS Graceful Shutdown not supported\n0x84-0xFFFFFFFF\nReserved\n6.Processing Sequence for Graceful Shutdown Request:\nFollowing receipt of the Graceful Shutdown Request (see Table 5-166, value 0x81) the OS will be responsible for responding with one of the following status codes:\n\u2022 0x80 (OS Shutdown Request denied) \u2013This value will be sent if the OS is not capable of performing a graceful shutdown.\n\u2022 0x81 (OS Shutdown in progress) The OS has initiated the graceful shutdown procedure.\n\u2022 0x83 (OS Graceful Shutdown not supported) The OS does not support the Graceful Shutdown Request.\nIf the OS does initiate a graceful shutdown it should continue to generate the \u201cOS Shutdown in progress\u201d message (_OST source event 0x100 status code 0x81) every 10 seconds. This functions as a heartbeat so that the service which requested the graceful shutdown knows that the request is currently being processed. The platform should assume that the OS shutdown is not proceeding if it does not receive the \u201cOS Shutdown in progress\u201d message for 60 seconds.\nWhen the graceful shutdown procedure has completed the OSPM will send the \u201cOS Shutdown completed\u201d message and then transition the platform to the G2 \u201csoft-off\u201d power state.\nTable 6-209 Ejection Request / Ejection Processing (Source Events: 0x03 and 0x103) Status Codes\nStatus Code\n0x80\nDevice ejection not supported by OSPM\n0x81\nDevice in use by application\n0x82\nDevice Busy\n0x83\nEjection dependency is busy or not supported for ejection by OSPM\n0x84\nEjection is in progress (pending)\n0x85-0xFFFFFFFF\nReserved\nTable 6-210 Insertion Processing (Source Event: 0x200) Status Codes\nStatus Code\n0x80\nDevice insertion in progress (pending)\n0x81\nDevice driver load failure\n0x82\nDevice insertion not supported by OSPM\n0x83-0x8F\nReserved\n0x90-0x9F\nInsertion failure encodings:\nBit [3]\n Resources Unavailable as described by the following bit\nBus or Segment Numbers\n \nBit [2]\nInterrupts\n \nBit [1]\nI/O\n \nBit [0]\nMemory\n0xA0-0xFFFFFFFF\nReserved\n \nIt is possible for the platform to issue multiple notifications to OSPM and for OSPM to process the notifications asynchronously. As such, OSPM may invoke _OST for notifications independent of the order the notification are conveyed by the platform or by software to OSPM.\nThe figure below provides and example event flow of device ejection on a platform employing the _OST object.\nFigure 6-34 Device Ejection Flow Example Using _OST\nNote: To maintain compatibility with OSPM implementations of previous revisions of the ACPI specification, the platform must not rely on OSPM\u2019s evaluation of the _OST object for proper platform operation.", - "example": "" - }, - { - "title": "_RMV (Remove)", - "syntax": "", - "arguments": "", - "description": "The optional _RMV object indicates to OSPM whether the device can be removed while the system is in the working state and does not require any ACPI system firmware actions to be performed for the device to be safely removed from the system (in other words, any device that only supports surprise-style removal). Any such removable device that does not have _LCK or _EJx control methods must have an _RMV object. This allows OSPM to indicate to the user that the device can be removed and to provide a way for shutting down the device before removing it. OSPM will transition the device into D3 before telling the user it is safe to remove the device.\nThis method is reevaluated after a device-check notification.", - "example": "" - }, - { - "title": "_STA (Status)", - "syntax": "", - "arguments": "", - "description": "This object returns the current status of a device, which can be one of the following: enabled, disabled, or removed.\nOSPM evaluates the _STA object before it evaluates a device _INI method. The return values of the Present and Functioning bits determines whether _INI should be evaluated and whether children of the device should be enumerated and initialized. See Section 6.5.1, \u201c_INI (Init)\u201d.\nIf a device object describes a device that is not on an enumerable bus and the device object does not have an _STA object, then OSPM assumes that the device is present, enabled, shown in the UI, and functioning.\nThis method must not reference any operation regions that have not been declared available by a _REG method.\nByte 0\nResource Identifier\nValue = 0x8D, (10001101B) Type = 1, Large item name = 0x0D\nByte 1\nLength, bits[7:0]\nVariable length, minimum value = 0x0F + L (15 + length of the\nResource Source Name string)\nByte 2\nLength, bits[15:8]\nVariable length, minimum value = 0x00\nByte 3\nRevision ID\nIndicates the revision for the Pin Function Descriptor. This value is 1\nByte 4\nFlags [7:0]\nBit [7:1] - Reserved. Must be 0.\nBit [0] - IO Sharing, _SHR\n 0x0 = Exclusive: This function is used exclusively by one device.\n 0x1 = Shared: This function is shared by two or more devices.\nByte 5\nFlags [15:8]\nReserved. Must be 0.\nByte 6\nPin pull configuration\nCan be one of PullDefault, PullUp, PullDown, PullNone or a vendor-supplied value in the range 128-255.\nByte 7\nFunction number (low byte)\nThe function number in which the pin is configured. This number is provider-specific.\nByte 8\nFunction number (high byte)\nThe function number in which the pin is configured. This number is provider-specific.\nByte 9\nPin table offset (low byte)\nOffset to the start of the pin table (low byte). The offset is relative to the start of this descriptor.\n \nByte Offset\nField Name\nByte 10\nPin table offset (high byte)\nOffset to the start of the pin table (high byte). The offset is relative to the start of this descriptor.\nByte 11\nResource source index\nReserved for future use. This field must be 0.\nByte 12\nResource source name index (low byte)\nOffset to the start of the resource source name (low byte). The offset is relative to the start of this descriptor.\nByte 13\nResource source name index (high byte)\nOffset to the start of the resource source name (high byte). The offset is relative to the start of this descriptor.\nByte 14\nVendor data offset (low byte)\n(low byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 15\nVendor data offset (high byte)\n(high byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 16\nVendor data length (low byte)\nLength of Vendor-defined Data (low-byte).\nByte 17\nVendor data length (high byte)\nLength of Vendor-defined Data (high-byte).\nByte PinTableOffset[15:0] + 2n (n is the index into the pin table)Byte PinTableOffset[15:0] + 2n + 1 (n is the index into the pin table)\nPin Number, bits [15:8]\nProvider-relative pin number (high byte). _PIN[15:8]. Pin numbers are zero-based.\nByte PinTableOffset[15:0] + 2n + 1 (n is the index into the pin table)\nByte\nResourceSourceNameOffset[15:0]\nResource Source (length = L)\nName of the function config provider to which this descriptor applies. The name can be a fullyqualified name, a relative name or a name segment that utilizes the namespace search\nByte VendorDataOffset[15:0]\nVendor-defined Data\n(Optional)\nData specific to the GPIO controller device supplied by a vendor. This data is provided to the device driver for this GPIO Controller. _VEN.\n6.Pin Configuration Descriptor\nTable 6-245 Pin Configuration Descriptor Definition\nByte Offset\nField Name\nByte 0\nResource Identifier\nValue = 0x8F, (10001111B) Type = 1, Large item name = 0x0F\nByte 1\nLength, bits[7:0]\nVariable length, minimum value = 0x13 + L (19 + length of the\nResource Source Name string)\nByte 2\nLength, bits[15:8]\nVariable length, minimum value = 0x00\nByte 3\nRevision ID\nIndicates the revision for the Function Configuration Descriptor. This value is 1\nByte 4\nFlags [7:0]\nBit [7:2] - Reserved. Must be 0.\nBit [1] - Consumer/Producer\n 0x1: This device consumes this resource\n 0x0: This device produces and consumes this resource\nBit [0] - IO Sharing, _SHR\n 0x0 = Exclusive: This function is used exclusively by one device.\n 0x1 = Shared: This function is shared by two or more devices.\nByte 5\nFlags [15:8]\nReserved. Must be 0.\nByte6\nPin Configuration Type, _TYP\nThe pin configuration type (see Table 19-434).\nByte 7\nPin Configuration\nValue, _VAL, bits [7:0]\nThe pin configuration value associated with the pin configuration type (see Table 19-434).\nByte 8\nPin Configuration\nValue, _VAL, bits\n[15:8]\nThe pin configuration value associated with the pin configuration type (see Table 19-434).\nByte 9\nPin Configuration Value, _VAL, bits\n[23:16]\nThe pin configuration value associated with the pin configuration type (see Table 19-434).\nByte 10\nPin Configuration\nValue, _VAL, bits\n[31:24]\nThe pin configuration value associated with the pin configuration type (see Table 19-434).\nByte 11\nPin Table\nOffset[7:0]\nOffset to the start of the pin table (low byte). The offset is relative to the start of this descriptor.\nByte 12\nPin Table\nOffset[15:8]\nOffset to the start of the pin table (high byte). The offset is relative to the start of this descriptor.\n \nByte Offset\nField Name\nByte 13\nResource\nSource Index\nReserved for future use. This field must be 0.\nByte 14\nResource\nSource Name\nOffset[7:0]\nOffset to the start of the resource source name (low byte). The offset is relative to the start of this descriptor.\nByte 15\nResource\nSource Name\nOffset[15:8]\nOffset to the start of the resource source name (high byte). The offset is relative to the start of this descriptor.\nByte 16\nVendor Data\nOffset[7:0]\n(low byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 17\nVendor Data\nOffset[15:8]\n(high byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 18\nVendor Data\nLength [7:0]\nLength of Vendor-defined Data (low-byte).\nByte 19\nVendor Data\nLength [15:8]\nLength of Vendor-defined Data (high-byte).\nByte PinTableOffset[15:0] + 2n (n is the index into the pin table)\nPin Number, _PIN, bits [7:0]\nProvider-relative pin number (low byte). Pin numbers are zero-based.\nByte PinTableOffset[15:0] + 2n + 1 (n is the index into the pin table)\nPin Number, _PIN, bits [15:8]\nProvider-relative pin number (high byte). Pin numbers are zero-based.\nByte\nResourceSourceNameOffset[15:0]\nResource Source (length = L)\nName of the pin controller to which this descriptor applies. The name can be a fullyqualified name, a relative name or a name segment that utilizes the namespace search\nByte VendorDataOffset[15:0]\nVendor-defined Data, _VEN\n(Optional)\nData specific to the pin controller device supplied by a vendor. This data is provided to the device driver for this pin controller.\n6.Pin Group Descriptor\nTable 6-246 Pin Group Descriptor Definition\nByte Offset\nField Name\nByte 0\nResource Identifier\nValue = 0x90, (10010000B) Type = 1, Large item name = 0x10\nByte 1\nLength [7:0]\nVariable length, minimum value = 0x0B + L (11 + length of the Resource Label)\nByte 2\nLength [15:8]\nValue = 0x00\nByte 3\nRevision ID\nIndicates the revision for the Pin Group Descriptor. This value is 1.\nByte 4\nFlags [7:0]\n[7:1] Reserved. Must be 0.\nBit [0] - Consumer/Producer\n 0x1: This device consumes this resource\n 0x0: This device produces and consumes this resource\nByte 5\nFlags [15:8]\nReserved. Must be 0.\nByte 6\nPin table offset [7:0]\nOffset to the start of the pin table (low byte). The offset is relative to the start of this descriptor.\nByte 7\nPin table offset [15:8]\nOffset to the start of the pin table (high byte). The offset is relative to the start of this descriptor.\nByte 8\nResource label offset [7:0]\nOffset to the start of the resource label (low byte). The offset is relative to the start of this descriptor.\nThe length of the resource label string can be calculated from length L = Vendor data offset Resource label offset. The length includes the string\u2019s terminating \u2018\\0\u2019 character.\nByte 9\nResource label offset [15:8]\nOffset to the start of the resource label (high byte). The offset is relative to the start of this descriptor.\nByte 10\nVendor data offset [7:0]\n(low byte) Offset to the start of the Vendordefined Data (the last byte of the Resource label offset (high byte) + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the Resource label offset (high byte) + 1. The offset is relative to the start of this descriptor.\nByte Offset\nField Name\nByte11\nVendor data offset [15:8]\n(high byte) Offset to the start of the Vendordefined Data (the last byte of the Pin table offset (high byte) + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the Pin table offset (high byte) + 1. The offset is relative to the start of this descriptor.\nByte 12\nVendor data length [7:0]\nLength of Vendor-defined Data (low-byte).\nByte 13\nVendor data length [15:8]\nLength of Vendor-defined Data (high-byte).\nByte PinTableOffset[15:0] + 2n (n is the index into the pin table)\nPin Number, _PIN [7:0]\nProvider-relative pin number (low byte). Pin numbers are zero-based.\nByte PinTableOffset[15:0] + 2n + 1 (n is the index into the pin table)\nPin Number, _PIN [15:8]\nProvider-relative pin number (high byte). Pin numbers are zero-based.\nByte ResourceLabelOffset[15:0]\nResource Label (length = L)\nLabel for the resource (string). Can be any nonempty string and is used by resource consumers to refer to this resource by name. Always terminated by \u2018\\0\u2019.\nByte VendorDataOffset[15:0]\nVendor-defined Data, _VEN\n(Optional)\nData specific to the GPIO controller device supplied by a vendor. This data is provided to the device driver for this GPIO Controller.\n6.Pin Group Function Descriptor\nTable 6-247 Pin Group Function Descriptor Definition\nByte Offset\nField Name\nByte 0\nResource Identifier\nValue = 0x91, (10010001B) Type = 1, Large item name = 0x11\nByte 1\nLength [7:0]\nVariable length, minimum value = 0x0E + L1 + L2 (14 + length of the\nResource Source Name string + length of the\nResource Source Label string)\nByte 2\nLength [15:8]\nVariable length, minimum value = 0x00\nByte 3\nRevision ID\nIndicates the revision for the Pin Function Descriptor. This value is 1\n \nByte Offset\nField Name\nByte 4\nFlags [7:0]\nBit [7:2] - Reserved. Must be 0.\nBit [1] - Consumer/Producer\n 0x1: This device consumes this resource\n 0x0: This device produces and consumes this resource\nBit [0] - IO Sharing, _SHR\n 0x0 = Exclusive: This function is used exclusively by one device.\n 0x1 = Shared: This function is shared by two or more devices.\nByte 5\nFlags [15:8]\nReserved. Must be 0.\nByte 6\nFunction number, _FUN [7:0]\nThe function number in which the pin is configured. This number is provider-specific.\nByte 7\nFunction number, _FUN [15:8]\nThe function number in which the pin is configured. This number is provider-specific.\nByte 8\nResource source index\nReserved for future use. This field must be 0.\nByte 9\nResource source name index [7:0]\nOffset to the start of the resource source name (low byte). The offset is relative to the start of this descriptor.\nByte 10\nResource source name index [15:8]\nOffset to the start of the resource source name (high byte). The offset is relative to the start of this descriptor.\nByte 11\nResource source label offset [7:0]\nOffset to the start of the Resource source label (low byte). The offset is relative to the start of this descriptor.\nThe length of the resource source label string can be calculated from length L2 = Vendor data offset Resource source label offset. The length includes the string\u2019s terminating \u2018\\0\u2019 character.\nByte 12\nResource source label offset [15:8]\nOffset to the start of the resource source label (high byte). The offset is relative to the start of this descriptor.\nByte Offset\nField Name\nByte 13\nVendor data offset [7:0]\n(low byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 14\nVendor data offset [15:8]\n(high byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 15\nVendor data length [7:0]\nLength of Vendor-defined Data (low-byte).\nByte 16\nVendor data length [15:8]\nLength of Vendor-defined Data (high-byte).\nByte\nResourceSourceNameOffset[15:0]\nResource Source (length = L1)\nName of the function config provider to which this descriptor applies. The name can be a fully-qualified name, a relative name or a name segment that utilizes the namespace search\nByte\nResourceSourceLabelOffset[15:0]\nResource Source Label (length = L2)\nThis name refers to the PinGroup resource in the current resource template buffer of the GPIO controller. The PinGroup resource is matched by comparing its ResourceLabel string to this field. Always terminated by \u2018\\0\u2019.\nByte VendorDataOffset[15:0]\nVendor-defined Data, _VEN\n(Optional)\nData specific to the GPIO controller device supplied by a vendor. This data is provided to the device driver for this GPIO Controller.\n6.Pin Group Configuration Descriptor\nTable 6-248 Pin Group Configuration Descriptor Description\nByte Offset\nField Name\nByte 0\nResource Identifier\nValue = 0x92, (10010001B) Type = 1, Large item name = 0x12\n \nByte Offset\nField Name\nByte 1\nLength, bits[7:0]\nVariable length, minimum value = 0x11 + L1 + L2 (17 + length of the\nResource Source Name string + length of the\nResource Source Label string)\nByte 2\nLength, bits[15:8]\nVariable length, minimum value = 0x00\nByte 3\nRevision ID\nIndicates the revision for the Function Configuration Descriptor. This value is 1\nByte 4\nFlags [7:0]\nBit [7:2] - Reserved. Must be 0.\nBit [1] - Consumer/Producer\n 0x1: This device consumes this resource\n 0x0: This device produces and consumes this resource\nBit [0] - IO Sharing, _SHR\n 0x0 = Exclusive: This function is used exclusively by one device.\n 0x1 = Shared: This function is shared by two or more devices.\nByte 5\nFlags [15:8]\nReserved. Must be 0.\nByte6\nPin Configuration Type, _TYP\nThe pin configuration type (see Table 19-435).\nByte 7\nPin Configuration Value, _VAL, bits\n[7:0]\nThe pin configuration value associated with the pin configuration type (see Table 19-435).\nByte 8\nPin Configuration Value, _VAL, bits\n[15:8]\nThe pin configuration value associated with the pin configuration type (see Table 19-435).\nByte 9\nPin Configuration Value, _VAL, bits\n[23:16]\nThe pin configuration value associated with the pin configuration type (see Table 19-435).\nByte 10\nPin Configuration Value, _VAL, bits\n[31:24]\nThe pin configuration value associated with the pin configuration type (see Table 19-435).\nByte 11\nResource\nSource Index\nReserved for future use. This field must be 0.\nByte 12\nResource\nSource Name\nOffset[7:0]\nOffset to the start of the resource source name (low byte). The offset is relative to the start of this descriptor.\n \nByte Offset\nField Name\nByte 13\nResource\nSource Name\nOffset[15:8]\nOffset to the start of the resource source name (high byte). The offset is relative to the start of this descriptor.\nByte 14\nResource source label offset (low byte)\nOffset to the start of the resource source label (low byte). The offset is relative to the start of this descriptor.\nThe length of the resource source label string can be calculated from length L2 = Vendor data offset Resource source label offset. The length includes the string\u2019s terminating \u2018\\0\u2019 character.\nByte 15\nResource source label offset (high byte)\nOffset to the start of the resource source label (high byte). The offset is relative to the start of this descriptor.\nByte 16\nVendor Data\nOffset[7:0]\n(low byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 17\nVendor Data\nOffset[15:8]\n(high byte) Offset to the start of the Vendordefined Data (the last byte of the\nResourceSource + 1). This value must always be valid to allow for length calculations. In the case where there is no Vendor Data, this offset still must refer to the last byte of the ResourceSource + 1. The offset is relative to the start of this descriptor.\nByte 18\nVendor Data\nLength [7:0]\nLength of Vendor-defined Data (low-byte).\nByte 19\nVendor Data\nLength [15:8]\nLength of Vendor-defined Data (high-byte).\nByte\nResourceSourceNameOffset[15:0]\nResource Source (length = L1)\nName of the pin controller to which this descriptor applies. The name can be a fullyqualified name, a relative name or a name segment that utilizes the namespace search\nByte\nResourceSourceLabelOffset[15:0]\nResource Source Label (length = L2)\nThis name refers to the PinGroup resource in current resource template buffer of the GPIO controller. The PinGroup resource is matched by comparing its ResourceLabel string to this field. Always terminated by \u2018\\0\u2019.\nByte Offset\nField Name\nByte VendorDataOffset[15:0]\nVendor-defined Data, _VEN\n(Optional)\nData specific to the pin controller device supplied by a vendor. This data is provided to the device driver for this pin controller.\n6.5 Other Objects and Control Methods\nTable 6-249 Other Objects and Methods\nObject\n_BBN\nPCI bus number set up by the platform boot firmware.\n_BDN\nCorrelates a docking station between ACPI and legacy interfaces.\n_DCK\nIndicates that the device is a docking station.\n_DEP\nIndicates device objects that OSPM should assign a higher priority in start ordering due to future operation region accesses.\n_FIT\nObject that evaluates to a buffer of NFIT Structures.\n_GLK\nIndicates the Global Lock must be acquired when accessing a device.\n_INI\nDevice initialization method that is run shortly after ACPI has been enabled.\n_LSI\nLabel Storage Information Returns information about the Label Storage Area associated with the NVDIMM object, including its size.\n_LSR\nLabel Storage Read Returns label data from the Label Storage Area of the NVDIMM object.\n_LSW\nLabel Storage Write Writes label data in to the Label Storage Area of the NVDIMM object.\n_REG\nNotifies AML code of a change in the availability of an operation region.\n_SEG\nIndicates a bus segment location.", - "example": "" - }, - { - "title": "_INI (Init)", - "syntax": "", - "arguments": "", - "description": "_INI is a device initialization object that performs device specific initialization. This control method is located under a device object and is run only when OSPM loads a description table. There are restrictions related to when this method is called and governing writing code for this method. The _INI method must only access Operation Regions that have been indicated to available as defined by the _REG method. The\n_REG method is described in Section 6.5.4, \u201c_REG (Region).\u201d This control method is run before _ADR, _CID, _HID, _SUN, and _UID are run.", - "example": "" - }, - { - "title": "_DCK (Dock)", - "syntax": "", - "arguments": "", - "description": "This control method is located in the device object that represents the docking station (that is, the device object with all the _EJx control methods for the docking station). The presence of _DCK indicates to the OS that the device is really a docking station.\n_DCK also controls the isolation logic on the docking connector. This allows an OS to prepare for docking before the bus is activated and devices appear on the bus.", - "example": "" - }, - { - "title": "_BDN (BIOS Dock Name)", - "syntax": "", - "arguments": "", - "description": "_BDN is used to correlate a docking station reported via ACPI and the same docking station reported via legacy interfaces. It is primarily used for upgrading over non-ACPI environments.", - "example": "" - }, - { - "title": "_REG (Region)", - "syntax": "", - "arguments": "", - "description": "The OS runs _REG control methods to inform AML code of a change in the availability of an operation region. When an operation region handler is unavailable, AML cannot access data fields in that region. (Operation region writes will be ignored and reads will return indeterminate data.)", - "example": "" - }, - { - "title": "_BBN (Base Bus Number)", - "syntax": "", - "arguments": "", - "description": "For multi-root PCI platforms, the _BBN object evaluates to the PCI bus number that the platform boot firmware assigns. This is needed to access a PCI_Config operation region for the specific bus. The _BBN object is located under a PCI host bridge and must be unique for every host bridge within a segment since it is the PCI bus number.", - "example": "" - }, - { - "title": "_SEG (Segment)", - "syntax": "", - "arguments": "", - "description": "The optional _SEG object is located under a PCI host bridge and evaluates to an integer that describes the\nPCI Segment Group (see PCI Firmware Specification v3.0). If _SEG does not exist, OSPM assumes that all PCI bus segments are in PCI Segment Group 0.", - "example": "" - }, - { - "title": "_GLK (Global Lock)", - "syntax": "", - "arguments": "", - "description": "This optional named object is located within the scope of a device object. This object returns a value that indicates to any entity that accesses this device (in other words, OSPM or any device driver) whether the Global Lock must be acquired when accessing the device. OS-based device accesses must be performed while in acquisition of the Global Lock when potentially contentious accesses to device resources are performed by non-OS code, such as System Management Mode (SMM)-based code in Intel architecturebased systems.\nNote: Default behavior: if _GLK is not present within the scope of a given device, then the Global Lock is not required for that device.", - "example": "" - }, - { - "title": "_DEP (Operation Region Dependencies)", - "syntax": "", - "arguments": "", - "description": "_DEP evaluates to a package and designates device objects that OSPM should assign a higher priority in start ordering due to future operation region accesses.\nTo increase the likelihood that an SPB operation region handler is available when needed, OSPM needs to know in advance which methods will access it -- _DEP provides OSPM with this information. While the _DEP keyword may be used to determine start ordering, only the _REG method (Section 6.5.4) callbacks can be relied upon to determine whether a region is accessible at a given point in time.", - "example": "" - }, - { - "title": "_FIT (Firmware Interface Table)", - "syntax": "", - "arguments": "", - "description": "This method evaluates to a buffer returning data in the format of a series of NFIT Structures (See Section 5.2.25). This method may appear under the NVDIMM root device (see Section 9.20.2). The _FIT method, when present, is always evaluated by OSPM.\n_FIT returns all the entries in the NFIT.\nThe NFIT Update Notification notification value for the NVDIMM root device (see Table 5-173) notifies OSPM that it needs to re-evaluate the _FIT method.\nNote: NFIT is an ACPI table enumerated at OS boot. In case of hot plug of NVDIMMs, the corresponding NFIT structures will not be present in NFIT. _FIT method is also used to provide these structures dynamically during hot plug.\n_LSI\nLabel Storage Information Returns information about the Label Storage Area associated with the NVDIMM object, including its size.\n_LSR\nLabel Storage Read Returns label data from the Label Storage Area of the NVDIMM object.\n_LSW\nLabel Storage Write Writes label data in to the Label Storage Area of the NVDIMM object.\n6._LSI (Label Storage Information)\nThis optional object returns information about the Label Storage Area for the requested device.\nStatus\nInteger\n(DWORD)\nIndicates the status of the _LSI request.\uf020 0x00000000 Success Returned package is valid\uf020\n0x00000001 Failure The rest of the returned package is not valid\nSizeOfLabelStorageArea\nInteger\n(DWORD)\nSize of the Label Storage Area in bytes\nMaxTransferLength\nInteger\n(DWORD)\nMaximum amount of data in bytes supported by a single call to the _LSR and _LSW methods. This is the minimum of the platform supported transfer size and the transfer size supported by the NVDIMM.\n0x00000000 - the NVDIMM does not support label storage.\nA non-zero value the NVDIMM supports label storage.\n6._LSR (Label Storage Read)\nThis optional object returns label data from the Label Storage Area starting at the specified offset.\nStatus\nInteger\n(DWORD)\nIndicates the status of the _LSR request.\uf020\n0x00000000 Success\uf020\n0x00000001 Failure\uf020\n0x00000002 Invalid Input Parameters\uf020\n -Offset > SizeOfLabelStorageArea reported with _LSI\uf020\n -Offset + TransferLength > SizeOfLabelStorageArea reported with _LSI\uf020\n -TransferLength > MaxTransferLength reported with _LSI\uf020\n0x00000003 Label Storage Area is locked and cannot be accessed\uf020\n0x00000004 HW failure prevented data from being read\uf020 Note: Any other non-zero values reflect a failure\nLabelData\nBuffer\nContains the returned label storage data. The size of the output is equal to TransferLength if Status is Success; otherwise, the contents of the output buffer shall be 0. The format of the Label Storage Area data is defined in UEFI.\n6._LSW (Label Storage Write)\nThis optional object writes label data to the Label Storage Area starting at the specified offset.\n_OFF\nSet the resource off.\n_ON\nSet the resource on.\n_RST\nObject that executes a platform level reset of all devices that list this resource in their _PRR object. (See Section for a description of this object.)\n_STA\nObject that evaluates to the current on or off state of the Power Resource. 0\u2013OFF, 1\u2013ON", - "example": "" - }, - { - "title": "_OFF", - "syntax": "", - "arguments": "", - "description": "This power resource control method puts the power resource into the OFF state. The control method must not complete until the power resource is off, including any required sequencing delays between, or after, operations on the power resource. OSPM is required to turn on or off only one resource at a time. The AML code can use Stall or Sleep within the method to cause the proper sequencing delays. OSPM is not required to run the _STA method to confirm that the resource has been successfully turned off, and may run the _OFF method repeatedly, even if the resource is already off.", - "example": "" - }, - { - "title": "_ON", - "syntax": "", - "arguments": "", - "description": "This power resource control method puts the power resource into the ON state. The control method must not complete until the power resource is on, including any required sequencing delays between, or after, operations on the power resource. OSPM is required to turn on or off only one resource at a time. The AML code can use Stall or Sleep within the method to cause the proper sequencing delays. OSPM is not required to run the _STA method to confirm that the resource has been successfully turned on, and may run the _ON method repeatedly, even if the resource is already on.", - "example": "" - }, - { - "title": "_STA (Status)", - "syntax": "", - "arguments": "", - "description": "Returns the current ON or OFF status for the power resource.\n_DSW\nControl method that enables or disables the device\u2019s wake function for device-only wake.\n_PS0\nControl method that puts the device in the D0 device state (device fully on).\n_PS1\nControl method that puts the device in the D1 device state.\n_PS2\nControl method that puts the device in the D2 device state.\n_PS3\nControl method that puts the device in the D3 device state (device off).\n_PSC\nObject that evaluates to the device\u2019s current power state.\n_PR0\nObject that evaluates to the device\u2019s power requirements in the D0 device state (device fully on).\n_PR1\nObject that evaluates to the device\u2019s power requirements in the D1 device state. The only devices that supply this level are those that can achieve the defined D1 device state according to the related device class.\n_PR2\nObject that evaluates to the device\u2019s power requirements in the D2 device state. The only devices that supply this level are those that can achieve the defined D2 device state according to the related device class.\n_PR3\nObject that evaluates to the device\u2019s power requirements in the D3hot device state.\n_PRW\nObject that evaluates to the device\u2019s power requirements in order to wake the system from a system sleeping state.\n_PSW\nControl method that enables or disables the device\u2019s wake function.\n_IRC\nObject that signifies the device has a significant inrush current draw.\nObject\n_S1D\nShallowest D-state supported by the device in the S1 state\n_S2D\nShallowest D-state supported by the device in the S2 state\n_S3D\nShallowest D-state supported by the device in the S3 state\n_S4D\nShallowest D-state supported by the device in the S4 state\n_S0W\nDeepest D-state supported by the device in the S0 state which can wake the device\n_S1W\nDeepest D-state supported by the device in the S1 state which can wake the system.\n_S2W\nDeepest D-state supported by the device in the S2 state which can wake the system.\n_S3W\nDeepest D-state supported by the device in the S3 state which can wake the system.\n_S4W\nDeepest D-state supported by the device in the S4 state which can wake the system.\n_RST\nControl method that executes a function level reset of the device.\n_PRR\nObject that evaluates to the device's platform level reset requirements.", - "example": "" - }, - { - "title": "_DSW (Device Sleep Wake)", - "syntax": "", - "arguments": "", - "description": "In addition to _PRW, this control method can be used to enable or disable the device\u2019s ability to wake a sleeping system. This control method can only access Operation Regions that are either always available while in a system working state or that are available when the Power Resources referenced by the _PRW object are all ON. For example, do not put a power plane control for a bus controller within configuration space located behind the bus. The method should enable the device only for the last system state/device state combination passed in by OSPM. OSPM will only pass in combinations allowed by the _SxD and _SxW objects.\nThe arguments provided to _DSW indicate the eventual Device State the device will be transitioned to and the eventual system state that the system will be transitioned to. The target system state is allowed to be the system working state (S0). The _DSW method will be run before the device is placed in the designated state and also before the system is placed in the designated system state.\nCompatibility Note: The _PSW method was deprecated in ACPI 3.0. The _DSW method should be used instead. OSPM will only use the _PSW method if OSPM does not support _DSW or if the _DSW method is not present.", - "example": "" - }, - { - "title": "_PS0 (Power State 0)", - "syntax": "", - "arguments": "", - "description": "This Control Method is used to put the specific device into its D0 state. This Control Method can only access Operation Regions that are either always available while in a system working state or that are available when the Power Resources references by the _PR0 object are all ON.", - "example": "" - }, - { - "title": "_PS1 (Power State 1)", - "syntax": "", - "arguments": "", - "description": "This control method is used to put the specific device into its D1 state. This control method can only access Operation Regions that are either always available while in the system working state (S0) or that are available when the Power Resources referenced by the _PR0 object are all ON.", - "example": "" - }, - { - "title": "_PS2 (Power State 2)", - "syntax": "", - "arguments": "", - "description": "This control method is used to put the specific device into its D2 state. This control method can only access Operation Regions that are either always available while in the system working state (S0) or that are available when the Power Resources referenced by the _PR0 and _PR1 objects are all ON.", - "example": "" - }, - { - "title": "_PS3 (Power State 3)", - "syntax": "", - "arguments": "", - "description": "This control method is used to put the specific device into its D3 state. This control method can only access Operation Regions that are either always available while in the system working state (S0) or that are available when the Power Resources referenced by the _PR0, _PR1 and PR2 objects are all ON.", - "example": "" - }, - { - "title": "_PSC (Power State Current)", - "syntax": "", - "arguments": "", - "description": "This control method evaluates to the current device state. This control method is not required if the device state can be inferred by the Power Resource settings. This would be the case when the device does not require a _PS0, _PS1, _PS2, or _PS3 control method.", - "example": "" - }, - { - "title": "_PSE (Power State for Enumeration)", - "syntax": "", - "arguments": "", - "description": "This control method is used to put a device into a powered mode appropriate for enumeration by its parent bus. This control method can only access Operation Regions that are either always available while in a system working state or that are available when the Power Resources referenced by the _PRE object are all ON.", - "example": "" - }, - { - "title": "_PR0 (Power Resources for D0)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to a list of power resources that are dependent on this device. For OSPM to put the device in the D0 device state, the following must occur:\n1. All Power Resources referenced by elements 1 through N must be in the ON state.\n2. All Power Resources no longer referenced by any device in the system must be in the OFF state.\n3. If present, the _PS0 control method is executed to set the device into the D0 device state.\n1\nobject reference\nReference to required Power Resource #0\nN\nobject reference\nReference to required Power Resource #N\n_PR0 must return the same data each time it is evaluated. All power resources referenced must exist in the namespace.", - "example": "" - }, - { - "title": "_PR1 (Power Resources for D1)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to a list of power resources upon which this device is dependent when it is in the D1 state. For OSPM to transition the device from the D0 state into the D1 state, the following must occur, in order:\n1. If present, the _PS1 control method is executed to set the device into the D1 device state.\n2. All Power Resources referenced by elements 1 through N must be in the ON state.\n3. All Power Resources no longer referenced by any device in the system must be in the OFF state.", - "example": "" - }, - { - "title": "_PR2 (Power Resources for D2)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to a list of power resources upon which this device is dependent when it is in the D2 state. For OSPM to transition the device into the D2 state, the following must occur, in order:\n1. If present, the _PS2 control method is executed to set the device into the D2 device state.\n2. All Power Resources referenced by elements 1 through N must be in the ON state.\n3. All Power Resources no longer referenced by any device in the system must be in the OFF state.", - "example": "" - }, - { - "title": "_PR3 (Power Resources for D3hot)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to a list of power resources upon which this device is dependent when it is in the\nD3hot state. For OSPM to transition the device into the D3hot state, the following must occur, in order:\n1. If present, the _PS3 control method is executed to set the device into the D3hot device state.\n2. All Power Resources referenced by elements 1 through N must be in the ON state.\n3. All Power Resources no longer referenced by any device in the system must be in the OFF state.", - "example": "" - }, - { - "title": "_PRE (Power Resources for Enumeration)", - "syntax": "", - "arguments": "", - "description": "This object appears under a device and evaluates to a list of power resources that are required for enumeration of the device by its parent bus. For the bus driver to enumerate any devices while they are in the D3Cold device state, OSPM must ensure that the following occur:\n1. All Power Resources referenced by elements 1 through N must be in the ON state.\n2. If present, the _PSE control method is executed to perform any actions on the device to make it accessible for enumeration.", - "example": "" - }, - { - "title": "_PRW (Power Resources for Wake)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to a list of power resources upon which this device depends for wake. It also contains additional information needed for wake, including wake events and sleep or soft-off state information. _PRW is only required for devices that have the ability to wake the system from a system sleeping state.\nFour types of general purpose events are supported:\n\u2022 GPEs that are defined by a GPE block described within the FADT.\n\u2022 GPEs that are defined by a GPE Block Device.\n\u2022 GPIO-signaled events that are defined by _AEI object of the GPIO controller device\n\u2022 Interrupt-signaled events that are defined by _CRS object of the Generic Event Device (GED)\nThe four types of events are differentiated by the type of the EventInfo object in the returned package.\nFor FADT-based GPEs, EventInfo is an Integer containing a bit index. For Block Device-based GPEs, EventInfo is a Package containing a Reference to the parent block device and an Integer containing a bit index. For GPIO-signaled events, EventInfo is a Package containing a Reference to the GPIO controller device and an Integer containing the index of the event in the _AEI object (starting from zero). For Interrupt-signaled events, EventInfo is a Package containing a Reference to the GED and an Integer containing the index of the event in the _CRS object (starting from zero).\nFor HW-Reduced ACPI platforms that do not support wake on GPIO-signaled or Interrupt-signaled events, the EventInfo structure is an Integer with value of zero, and is ignored by OSPM. Therefore, _PRW is only required on such platforms if power resources for wakeup must be managed by OSPM (e.g. the _PRW provides a list of Power Resources). Instead, for a device to wake the system, its interrupt must be wakecapable and enabled by the driver. See Section 3.11.1.1\"Interrupt-based Wake Events\".", - "example": "" - }, - { - "title": "_PSW (Power State Wake)", - "syntax": "", - "arguments": "", - "description": "In addition to the _PRW control method, this control method can be used to enable or disable the device\u2019s ability to wake a sleeping system. This control method can only access Operation Regions that are either always available while in a system working state or that are available when the Power Resources references by the _PRW object are all ON. For example, do not put a power plane control for a bus controller within configuration space located behind the bus.\nNote: Regarding compatability--The _PSW method was deprecated in ACPI 3.0. OSPM must use _DSW if it is present. Otherwise, it may use _PSW.", - "example": "" - }, - { - "title": "_IRC (In Rush Current)", - "syntax": "", - "arguments": "", - "description": "Indicates that this device can cause a significant in-rush current when transitioning to state D0.", - "example": "" - }, - { - "title": "_S1D (S1 Device State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the shallowest D-state supported by this device in the S1 system sleeping state. _S1D must return the same integer each time it is evaluated. This value overrides an S-state to D-state mapping OSPM may ascertain from the device\u2019s power resource declarations. See Table 7-257 for valid return values.", - "example": "" - }, - { - "title": "_S2D (S2 Device State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the shallowest D-state supported by this device in the S2 system sleeping state. _S2D must return the same integer each time it is evaluated. This value overrides an S-state to D-state mapping OSPM may ascertain from the device\u2019s power resource declarations. See Table 7-257 for valid return values.", - "example": "" - }, - { - "title": "_S3D (S3 Device State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the shallowest D-state supported by this device in the S3 system sleeping state. _S3D must return the same integer each time it is evaluated. This value overrides an S-state to D-state mapping OSPM may ascertain from the device\u2019s power resource declarations. See Table 7-257 for valid return values.", - "example": "" - }, - { - "title": "_S4D (S4 Device State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the shallowest D-state supported by this device in the S4 system sleeping state. _S4D must return the same integer each time it is evaluated. This value overrides an S-state to D-state mapping OSPM may ascertain from the device\u2019s power resource declarations. See Table 7-3 for valid return values.", - "example": "" - }, - { - "title": "_S0W (S0 Device Wake State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the deepest D-state supported by this device in the S0 system sleeping state where the device can wake itself.", - "example": "" - }, - { - "title": "_S1W (S1 Device Wake State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the deepest D-state supported by this device in the S1 system sleeping state that can wake the system.", - "example": "" - }, - { - "title": "_S2W (S2 Device Wake State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the deepest D-state supported by this device in the S2 system sleeping state that can wake the system.", - "example": "" - }, - { - "title": "_S3W (S3 Device Wake State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the deepest D-state supported by this device in the S3 system sleeping state that can wake the system.", - "example": "" - }, - { - "title": "_S4W (S4 Device Wake State)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to an integer that conveys to OSPM the deepest D-state supported by this device in the S4 system sleeping state that can wake the system.", - "example": "" - }, - { - "title": "_RST (Device Reset)", - "syntax": "", - "arguments": "", - "description": "This object executes a reset on the associated device or devices. If included in a device context, the reset must not affect any other ACPI-described devices; if included in a power resource for reset (_PRR, Section 7.3.26) the reset must affect all ACPI-described devices that reference it.\nWhen this object is described in a device context, it executes a function level reset that only affects the device it is associated with; neither parent nor children should be affected by the execution of this reset. Executing this must only result in this device resetting without the device appearing as if it has been removed from the bus altogether, to prevent OSPM re-enumeration of devices on hot-pluggable buses (e.g. USB).\nIf a device reset is supported by the platform, but cannot meet the function level and bus requirement, the device should instead implement a _PRR (Section 7.3.26).\nDevices can define both a _RST and a _PRR if supported by the hardware.", - "example": "" - }, - { - "title": "_PRR (Power Resource for Reset)", - "syntax": "", - "arguments": "", - "description": "This object evaluates to a single reference to a power resource. The power resource that this references must implement a _RST method (Section 7.3.25).\n\\_PTS\nControl method used to notify the platform of impending sleep transition.\n\\_S0\nPackage that defines system \\_S0 state mode.\n\\_S1\nPackage that defines system \\_S1 state mode.\n\\_S2\nPackage that defines system \\_S2 state mode.\n\\_S3\nPackage that defines system \\_S3 state mode.\n\\_S4\nPackage that defines system \\_S4 state mode.\n\\_S5\nPackage that defines system \\_S5 state mode.\n\\_TTS\nControl method used to prepare to sleep and run once awakened\n\\_WAK\nControl method run once awakened.\nNote: Compatibility issue: The _BFS (Back From Sleep) and _GTS (Going To Sleep) methods were deprecated in ACPI 5.0A.\n\\_PTS (Prepare To Sleep)\nThe _PTS control method is executed by the OS during the sleep transition process for S1, S2, S3, S4, and for orderly S5 shutdown. The sleeping state value (For example, 1, 2, 3, 4 or 5 for the S5 soft-off state) is passed to the _PTS control method. This method is called after OSPM has notified native device drivers of the sleep state transition and before the OSPM has had a chance to fully prepare the system for a sleep state transition. Thus, this control method can be executed a relatively long time before actually entering the desired sleeping state. If OSPM aborts the sleep state transition, OSPM should run the _WAK method to indicate this condition to the platform.\n1\n0\nValue for PM1a_CNT.SLP_TYP register to enter this system state. On HW-reduced platforms, this is the HW-reduced Sleep Type value for SLEEP_CONTROL_REG.SLP_TYP.\n1\n1\nValue for PM1b_CNT.SLP_TYP register to enter this system state. To enter any given state, OSPM must write the PM1a_CNT.SLP_TYP register before the\nPM1b_CNT.SLP_TYP register. On HW-reduced platforms, this value is ignored.\n2\n2\nReserved\nStates S1\u2013S4 represent some system sleeping state. The S0 state is the system working state. Transition into the S0 state from some other system state (such as sleeping) is automatic, and, by virtue that instructions are being executed, OSPM assumes the system to be in the S0 state. Transition into any system sleeping state is only accomplished by the operating software directing the hardware to enter the appropriate state, and the operating software can only do this within the requirements defined in the Power Resource and Bus/Device Package objects.\nAll run-time system state transitions (for example, to and from the S0 state), except S4 and S5, are done similarly such that the code sequence to do this is the following:\n/*\n * Intel Architecture SetSleepingState example */\n ULONG\n SetSystemSleeping (\n IN ULONG NewState\n )\n {\n PROCESSOR_CONTEXT Context;\n ULONG PowerSeqeunce;\n BOOLEAN FlushCaches;\n USHORT SlpTyp;\n// Required environment: Executing on the system boot\n// processor. All other processors stopped. Interrupts // disabled. All Power Resources (and devices) are in // corresponding device state to support NewState.\n // Get h/w attributes for this system state\n FlushCaches = SleepType[NewState].FlushCache;\n SlpTyp = SleepType[NewState].SlpTyp & SLP_TYP_MASK;\n _asm {\n lea eax, OsResumeContext\n push eax ; Build real mode handler the resume push offset sp50 ; context, with eip = sp50 call SaveProcessorState\n mov eax, ResumeVector ; set firmware\u2019s resume vector mov [eax], offset OsRealModeResumeCode\n mov edx, PM1a_STS ; Make sure wake status is clear mov ax, WAK_STS ; (cleared by asserting the bit out dx, ax ; in the status register)\n mov edx, PM1b_STS ; out dx, ax ;\n and eax, not SLP_TYP_MASK\n or eax, SlpTyp ; set SLP_TYP or ax, SLP_EN ; set SLP_EN\n cmp FlushCaches, 0\n jz short sp10 ; If needed, ensure no dirty data in\n call FlushProcessorCaches ; the caches while sleeping\n \nsp10: mov edx, PM1a_SLP_TYP ; get address for PM1a_SLP_TYP out dx, ax ; start h/w sequencing mov edx, PM1b_SLP_TYP ; get address for PM1b_SLP_TYP out dx, ax ; start h/w sequencing\n mov edx, PM1a_STS ; get address for PM1x_STS mov ecx, PM1b_STS\nsp20: in ax, dx ; wait for WAK status xchg edx, ecx test ax, WAK_STS jz short sp20\nsp50: \n}\n // Done..\n *ResumeVector = NULL; return 0; }\nOn HW-reduced ACPI platforms all run-time system state transitions (for example, to and from the S0 state) are done similarly, but include the following instead of PM1*_BLK register bit manipulation:\nAfter ensuring that any desired wake-capable interrupts are enabled, OSPM writes the HWreduced Sleep Type value to the Sleep Control Register and spins waiting for the WAK_STS bit of the Sleep Status Register to be set, indicating a platform transition to the Working state.\n7.System \\_S0 State (Working)\nWhile the system is in the S0 state, it is in the system working state. The behavior of this state is defined as:\n\u2022 The processors are either running, or in a C-state, or in an LPI state. The processor-complex context is maintained and instructions are executed as defined by any of these processor states.\n\u2022 Dynamic RAM context is maintained and is read/write by the processors.\n\u2022 Devices states are individually managed by the operating software and can be in any device state (D0, D1, D2, D3hot, or D3).\n\u2022 Power Resources are in a state compatible with the current device states.\nTransition into the S0 state from some system sleeping state is automatic, and by virtue that instructions are being executed OSPM, assumes the system to be in the S0 state.\n7.System \\_S1 State (Sleeping with Processor Context Maintained)\nWhile the system is in the S1 sleeping state, its behavior is the following:\n\u2022 The processors are not executing instructions. The processor-complex context is maintained.\n\u2022 Dynamic RAM context is maintained.\n\u2022 Power Resources are in a state compatible with the system S1 state. All Power Resources that supply a System-Level reference of S0 are in the OFF state.\n\u2022 Devices states are compatible with the current Power Resource states. Only devices that solely reference Power Resources that are in the ON state for a given device state can be in that device state. In all other cases, the device is in the D3 (off) state[8].\n\u2022 Devices that are enabled to wake the system and that can do so from their current device state can initiate a hardware event that transitions the system state to S0. This transition causes the processor to continue execution where it left off.\nTo transition into the S1 state, the OSPM must flush all processor caches.\n7.System \\_S2 State\nThe S2 sleeping state is logically deeper than the S1 state and is assumed to conserve more power. The behavior of this state is defined as:\n\u2022 The processors are not executing instructions. The processor-complex context is not maintained.\n\u2022 Dynamic RAM context is maintained.\n\u2022 Power Resources are in a state compatible with the system S2 state. All Power Resources that supply a System-Level reference of S0 or S1 are in the OFF state.\n\u2022 Devices states are compatible with the current Power Resource states. Only devices that solely reference Power Resources that are in the ON state for a given device state can be in that device state. In all other cases, the device is in the D3 (off) state.\n\u2022 Devices that are enabled to wake the system and that can do so from their current device state can initiate a hardware event that transitions the system state to S0. This transition causes the processor to begin execution at its boot location. The platform runtime firmware performs initialization of core functions as needed to exit an S2 state and passes control to the firmware resume vector. See Section for more details on platform firmware initialization.\nBecause the processor context can be lost while in the S2 state, the transition to the S2 state requires that the operating software flush all dirty cache to dynamic RAM (DRAM).\n7.System \\_S3 State\nThe S3 state is logically deeper than the S2 state and is assumed to conserve more power. The behavior of this state is defined as follows:\n\u2022 The processors are not executing instructions. The processor-complex context is not maintained.\n\u2022 Dynamic RAM context is maintained.\n\u2022 Power Resources are in a state compatible with the system S3 state. All Power Resources that supply a System-Level reference of S0, S1, or S2 are in the OFF state.\n\u2022 Devices states are compatible with the current Power Resource states. Only devices that solely reference Power Resources that are in the ON state for a given device state can be in that device state. In all other cases, the device is in the D3 (off) state.\n\u2022 Devices that are enabled to wake the system and that can do so from their current device state can initiate a hardware event that transitions the system state to S0. This transition causes the processor to begin execution at its boot location. The platform runtime firmware performs initialization of core functions as necessary to exit an S3 state and passes control to the firmware resume vector. See Section for more details on platform firmware initialization.\nFrom the software viewpoint, this state is functionally the same as the S2 state. The operational difference can be that some Power Resources that could be left ON to be in the S2 state might not be available to the S3 state. As such, additional devices may need to be in a deeper state for S3 than S2. Similarly, some device wake events can function in S2 but not S3.\nBecause the processor context can be lost while in the S3 state, the transition to the S3 state requires that the operating software flush all dirty cache to DRAM.\n7.System \\_S4 State\nWhile the system is in this state, it is in the system S4 sleeping state. The state is logically deeper than the S3 state and is assumed to conserve more power. The behavior of this state is defined as follows:\n\u2022 The processors are not executing instructions. The processor-complex context is not maintained.\n\u2022 DRAM context is not maintained.\n\u2022 Power Resources are in a state compatible with the system S4 state. All Power Resources that supply a System-Level reference of S0, S1, S2, or S3 are in the OFF state.\n\u2022 Devices states are compatible with the current Power Resource states. In other words, all devices are in the D3 state when the system state is S4.\n\u2022 Devices that are enabled to wake the system and that can do so from their device state in S4 can initiate a hardware event that transitions the system state to S0. This transition causes the processor to begin execution at its boot location.\nAfter OSPM has executed the _PTS control method and has put the entire system state into main memory, there are two ways that OSPM may handle the next phase of the S4 state transition; saving and restoring main memory. The first way is to use the operating system's drivers to access the disks and file system structures to save a copy of memory to disk and then initiate the hardware S4 sequence by setting the SLP_EN register bit. When the system wakes, the firmware performs a normal boot process and transfers control to the OS via the firmware_waking_vector loader. The OS then restores the system's memory and resumes execution.\nThe alternate method for entering the S4 state is to utilize the platform runtime firmware via the S4BIOS transition. The platform runtime firmware uses firmware to save a copy of memory to disk and then initiates the hardware S4 sequence. When the system wakes, the firmware restores memory from disk and wakes OSPM by transferring control to the FACS waking vector.\nThe S4BIOS transition is optional, but any system that supports this mechanism must support entering the S4 state via the direct OS mechanism. Thus the preferred mechanism for S4 support is the direct OS mechanism as it provides broader platform support. The alternate S4BIOS transition provides a way to achieve S4 support on operating systems that do not have support for the direct method.\n7.System \\_S5 State (Soft Off)\n The S5 state is similar to the S4 state except that OSPM does not save any context. The system is in the soft off state and requires a complete boot when awakened (platform boot firmware and OS). Software uses a different state value to distinguish between this state and the S4 state to allow for initial boot operations within the platform boot firmware to distinguish whether or not the boot is going to wake from a saved memory image. OSPM does not disable wake events before setting the SLP_EN bit when entering the S5 system state. This provides support for remote management initiatives by enabling Remote Start capability. An ACPI-compliant OS must provide an end user accessible mechanism for disabling all wake devices, with the exception of the system power button, from a single point in the user interface.", - "example": "" - }, - { - "title": "_ADR (Address)", - "syntax": "", - "arguments": "", - "description": "This object is used to supply OSPM with the address of a device on its parent bus. An _ADR object must be used when specifying the address of any device on a bus that has a standard enumeration algorithm (see Section 3.7, \u201cConfiguration and Plug and Play\u201d, for the situations when these devices do appear in the ACPI namespace).", - "example": "" - }, - { - "title": "_CID (Compatible ID)", - "syntax": "", - "arguments": "", - "description": "This optional object is used to supply OSPM with a device\u2019s Plug and Play-Compatible Device ID. Use _CID objects when a device has no other defined hardware standard method to report its compatible IDs.", - "example": "" - }, - { - "title": "_CLS (Class Code)", - "syntax": "", - "arguments": "", - "description": "This object is used to supply OSPM with the PCI-defined base-class, sub-class and programming interface for a device. This object is optional. However, it may be useful for loading generic drivers on hardware that is compatible with PCI -defined device classes, but that is not implemented on the PCI bus (and is therefore enumerated by ACPI.)", - "example": "" - }, - { - "title": "_DDN (DOS Device Name)", - "syntax": "", - "arguments": "", - "description": "This object is used to associate a logical name (for example, COM1) with a device. This name can be used by applications to connect to the device.", - "example": "" - }, - { - "title": "_HID (Hardware ID)", - "syntax": "", - "arguments": "", - "description": "This object is used to supply OSPM with the device\u2019s PNP ID or ACPI ID.[6]\n When describing a platform, use of any _HID objects is optional. However, a _HID object must be used to describe any device that will be enumerated by OSPM. OSPM only enumerates a device when no bus enumerator can detect the device ID. For example, devices on an ISA bus are enumerated by OSPM. Use the _ADR object to describe devices enumerated by bus enumerators other than OSPM.", - "example": "" - }, - { - "title": "_HRV (Hardware Revision)", - "syntax": "", - "arguments": "", - "description": "This object is used to supply OSPM with the device\u2019s hardware revision. The use of _HRV is optional.", - "example": "" - }, - { - "title": "_MLS (Multiple Language String)", - "syntax": "", - "arguments": "", - "description": "The _MLS object provides OSPM a human readable description of a device in multiple languages. This information may be provided to the end user when the OSPM is unable to get any other information about this device. Although this functionality is also provided by the _STR object, _MLS expands that functionality and provides vendors with the capability to provide multiple strings in multiple languages. The _MLS object evaluates to a package of packages. Each sub-package consists of a Language identifier and corresponding unicode string for a given locale. Specifying a language identifier allows OSPM to easily determine if support for displaying the Unicode string is available. OSPM can use this information to determine whether or not to display the device string, or which string is appropriate for a user\u2019s preferred locale.\nIt is assumed that OSPM will always support the primary English locale to accommodate English embedded in a non-English string, such as a brand name.\nIf OSPM doesn\u2019t support the specific sub-language ID it may choose to use the primary language ID for displaying device text.", - "example": "" - }, - { - "title": "_PLD (Physical Location of Device)", - "syntax": "", - "arguments": "", - "description": "This optional object is a method that conveys to OSPM a general description of the physical location of a device\u2019s external connection point. The _PLD may be child object for any ACPI Namespace object the system wants to describe. This information can be used by system software to describe to the user which specific connector or device input mechanism may be used for a given task or may need user intervention for correct operation. The _PLD should only be evaluated when its parent device is present as indicated by the device\u2019s presence mechanism (i.e. _STA or other)\nAn externally exposed device connection point can reside on any surface of a system\u2019s housing. The respective surfaces of a system\u2019s housing are identified by the \u201cPanel\u201d field (described below). The _PLD method returns data to describe the location of where the device\u2019s connection point resides and a Shape (described below) that may be rendered at that position. One physical device may have several connection points. A _PLD describes the offset and rotation of a single device connection point from an \u201corigin\u201d that resides in the lower left hand corner of its Panel.\nAll Panel references (Top, Bottom, Right, Left, etc.) are interpreted as though the user is facing the front of the system. For handheld mobile devices, the front panel is the one holding the display screen, and its origin is in the lower-left corner when the display is viewed in the Portrait orientation. For example, the Right Panel is the right side of the system as viewed from the front.\nAll \u201corigin\u201d references for a Panel are interpreted as its lower left corner when the user is facing the respective Panel. The Top Panel shall be viewed with the system is viewed resting on its Front Panel, and the Bottom Panel shall be viewed with the system resting on its Back Panel. All other Panels shall be viewed with the system resting on its Bottom Panel. Refer to Figure 6-29 for more information.\nFigure 6-29 System Panel and Panel Origin Positions\n The data bits also assume that if the system is capable of opening up like a laptop that the device may exist on the base of the laptop system or on the lid. In the case of the latter, the \u201cLid\u201d bit (described below) should be set indicating the device connection point is on the lid. If the device is on the lid, the description describes the device\u2019s connection point location when the system is opened with the lid up. If the device connection point is not on the lid, then the description describes the device\u2019s connection point location when the system with the lid closed.\nFigure 6-30 Laptop Panel and Panel Origin Positions\nTo render a view of a system Panel, all _PLDs that define the same Panel and Lid values are collected. The _PLDs are then sorted by the value of their Order field and the view of the panel is rendered by drawing the shapes of each connection point (in their correct Shape, Color, Horizontal Offset, Vertical Offset, Width, Height, and Orientation) starting with all Order = 0 _PLDs first. Refer to Figure 6-32 for an example.\nThe location of a device connection point may change as a result of the system connecting or disconnecting to a docking station or a port replicator. As such, Notify event of type 0x09 will cause OSPM to re-evaluate the _PLD object residing under the particular device notified. If a platform is unable to detect the change of connecting or disconnecting to a docking station or port replicator, a _PLD object should not be used to describe the device connection points that will change location after such an event.", - "example": "" - }, - { - "title": "_SUB (Subsystem ID)", - "syntax": "", - "arguments": "", - "description": "This object is used to supply OSPM with the device's Subsystem ID. The use of _SUB is optional.", - "example": "" - }, - { - "title": "_STR (String)", - "syntax": "", - "arguments": "", - "description": "The _STR object evaluates to a Unicode string that describes the device or thermal zone. It may be used by an OS to provide information to an end user. This information is particularly valuable when no other information is available.", - "example": "" - }, - { - "title": "_SUN (Slot User Number)", - "syntax": "", - "arguments": "", - "description": "_SUN is an object that evaluates to the slot-unique ID number for a slot. _SUN is used by OSPM UI to identify slots for the user. For example, this can be used for battery slots, PCI slots, PCMCIA slots, or swappable bay slots to inform the user of what devices are in each slot. _SUN evaluates to an integer that is the number to be used in the user interface.", - "example": "" - }, - { - "title": "_GL (Global Lock Mutex)", - "syntax": "", - "arguments": "", - "description": "This predefined object is a Mutex object that behaves like a Mutex as defined in Section 19.6.87, “Mutex (Declare Synchronization/Mutex Object),” with the added behavior that acquiring this Mutex also acquires the shared environment Global Lock defined in Section 5.2.10.1, “Global Lock.” This allows Control Methods to explicitly synchronize with the Global Lock if necessary.", - "example": "" - }, - { - "title": " _OSI (Operating System Interfaces)", - "syntax": "", - "arguments": "", - "description": "This method is used by the system firmware to query OSPM about interfaces and features that are supported by the host operating system. The usage and implementation model for this method is as follows:\n• The _OSI method is implemented within the operating system.\n• OSI is called by the firmware AML code, usually during initialization (such as via _INI method). Thus, _OSI is actually an “up-call” from the firmware AML to the OS – exactly the opposite of other control methods.\n• An _OSI invocation by the firmware is a request to the operating system: \"Do you support this interface/feature?\"\n• The host responds to this _OSI request with a simple yes or no (Ones/Zero, TRUE/FALSE, Supported/NotSupported)", - "example": "" - }, - { - "title": "_OS (OS Name Object)", - "syntax": "", - "arguments": "", - "description": "This predefined object evaluates to a string that identifies the operating system. In robust OSPM implementations, \\_OS evaluates differently for each OS release. This may allow AML code to accommodate differences in OSPM implementations. This value does not change with different revisions of the AML interpreter.", - "example": "" - }, - { - "title": "_REV (Revision Data Object)", - "syntax": "", - "arguments": "", - "description": "This predefined object evaluates to an Integer (DWORD) representing the revision of the ACPI Specification implemented by the specified \\_OS.", - "example": "" - }, - { - "title": "_DLM (DeviceLock Mutex)", - "syntax": "", - "arguments": "", - "description": "This object appears in a device scope when AML access to the device must be synchronized with the OS environment. It is used in conjunction with a standard Mutex object. With _DLM, the standard Mutex provides synchronization within the AML environment as usual, but also synchronizes with the OS environment.\n_DLM evaluates to a package of packages, each containing a reference to a Mutex and an optional resource template protected by the Mutex, If only the Mutex name is specified, then the sharing rules (i.e. which resources are protected by the lock) are defined by a predefined contract between the AML and the OS device driver. If the resource template is specified, then only those resources within the resource template are protected.", - "example": "" - }, - { - "title": "_PIC Method", - "syntax": "", - "arguments": "", - "description": "The \\_PIC optional method is used to report to the platform runtime firmware the current interrupt model used by the OS. This control method returns nothing. The argument passed into the method signifies the interrupt model OSPM has chosen, PIC mode, APIC mode, or SAPIC mode. Notice that calling this method is optional for OSPM. If the platform CPU architecture supports PIC mode and the method is never called, the platform runtime firmware must assume PIC mode. It is important that the platform runtime firmware save the value passed in by OSPM for later use during wake operations.", - "example": "" - }, - { - "title": "_UID (Unique ID)", - "syntax": "", - "arguments": "", - "description": "This object provides OSPM with a logical device ID that does not change across reboots. This object is optional, but is required when the device has no other way to report a persistent unique device ID. The _UID must be unique across all devices with either a common _HID or _CID. This is because a device needs to be uniquely identified to the OSPM, which may match on either a _HID or a _CID to identify the device. The uniqueness match must be true regardless of whether the OSPM uses the _HID or the _CID. OSPM typically uses the unique device ID to ensure that the device-specific information, such as network protocol binding information, is remembered for the device even if its relative location changes. For most integrated devices, this object contains a unique identifier.\nA _UID object evaluates to either a numeric value or a string.", - "example": "" - }, - { - "title": "_GPE", - "syntax": "", - "arguments": "", - "description": "General events in GPE register block.", - "example": "" - }, - { - "title": "_PR", - "syntax": "", - "arguments": "", - "description": "ACPI 1.0 Processor Namespace. ACPI 1.0 requires all Processor objects to be defined under this namespace. ACPI 2.0 and later allow Processor object definitions under the \\_SB namespace. Platforms may maintain the \\_PR namespace for compatibility with ACPI 1.0 operating systems, but it is otherwise deprecated. see the compatibility note in\nSection 5.2.12.12. An ACPI-compatible namespace may define Processor objects in either the \\_SB or \\_PR scope but not both.\nFor more information about defining Processor objects", - "example": "" - }, - { - "title": "_SB", - "syntax": "", - "arguments": "", - "description": "All Device/Bus Objects are defined under this namespace.", - "example": "" - }, - { - "title": "_TZ", - "syntax": "", - "arguments": "", - "description": "ACPI 1.0 Thermal Zone namespace. ACPI 1.0 requires all Thermal Zone objects to be defined under this namespace. Thermal Zone object definitions may now be defined under the \\_SB namespace. ACPI-compatible systems may maintain the \\_TZ namespace for compatibility with ACPI 1.0 operating systems. An ACPI-compatible namespace may define Thermal Zone objects in either the \\_SB or \\_TZ scope but not both.\nFor more information about defining Thermal Zone objects, see Section 11, “Thermal Management.”", - "example": "" - }, - { - "title": "_SI", - "syntax": "", - "arguments": "", - "description": "System indicator objects are defined under this namespace. For more information about defining system indicators, see Section 9.2, \\_SI System Indicators.”", - "example": "" - }, - { - "title": "_ACx", - "syntax": "", - "arguments": "", - "description": "Active Cooling returns the active cooling policy threshold values.", - "example": "" - }, - { - "title": "_ADR", - "syntax": "", - "arguments": "", - "description": "Address (1) returns the address of a device on its parent bus. \uf020 (2) returns a unique ID for the display output device.\uf020\n(3) resource descriptor field.", - "example": "" - }, - { - "title": "_AEI", - "syntax": "", - "arguments": "", - "description": "Designates those GPIO interrupts that shall be handled by OSPM as ACPI events", - "example": "" - }, - { - "title": "_ALC", - "syntax": "", - "arguments": "", - "description": "Ambient Light Chromaticity returns the ambient light color chromaticity.\nHeading ", - "example": "" - }, - { - "title": "_ALI", - "syntax": "", - "arguments": "", - "description": "Ambient Light Illuminance returns the ambient light brightness.", - "example": "" - }, - { - "title": "_ALN", - "syntax": "", - "arguments": "", - "description": "Alignment base alignment, resource descriptor field.", - "example": "" - }, - { - "title": "_ALP", - "syntax": "", - "arguments": "", - "description": "Ambient Light Polling returns the ambient light sensor polling frequency.", - "example": "" - }, - { - "title": "_ALR", - "syntax": "", - "arguments": "", - "description": "Ambient Light Response returns the ambient light brightness to display brightness mappings.", - "example": "" - }, - { - "title": "_ALT", - "syntax": "", - "arguments": "", - "description": "Ambient Light Temperature returns the ambient light color temperature.", - "example": "" - }, - { - "title": "_ALx", - "syntax": "", - "arguments": "", - "description": "Active List returns a list of active cooling device objects.", - "example": "" - }, - { - "title": "_ART", - "syntax": "", - "arguments": "", - "description": "Active cooling Relationship Table returns thermal relationship information between platform devices and fan devices.", - "example": "" - }, - { - "title": "_ASI", - "syntax": "", - "arguments": "", - "description": "Address Space Id resource descriptor field.", - "example": "" - }, - { - "title": "_ASZ", - "syntax": "", - "arguments": "", - "description": "Access Size resource descriptor field.", - "example": "" - }, - { - "title": "_ATT", - "syntax": "", - "arguments": "", - "description": "Type-Specific Attribute resource descriptor field.", - "example": "" - }, - { - "title": "_BAS", - "syntax": "", - "arguments": "", - "description": "Base Address range base address, resource descriptor field.", - "example": "" - }, - { - "title": "_BBN", - "syntax": "", - "arguments": "", - "description": "Bios Bus Number returns the PCI bus number returned by the platform firmware.", - "example": "" - }, - { - "title": "_BCL", - "syntax": "", - "arguments": "", - "description": "Brightness Control Levels returns a list of supported brightness control levels.", - "example": "" - }, - { - "title": "_BCM", - "syntax": "", - "arguments": "", - "description": "Brightness Control Method sets the brightness level of the display device.", - "example": "" - }, - { - "title": "_BCT", - "syntax": "", - "arguments": "", - "description": "Battery Charge Time returns time remaining to complete charging battery.", - "example": "" - }, - { - "title": "_BDN", - "syntax": "", - "arguments": "", - "description": "Bios Dock Name returns the Dock ID returned by the platform firmware.", - "example": "" - }, - { - "title": "_BIF", - "syntax": "", - "arguments": "", - "description": "Battery Information returns a Control Method Battery information block.", - "example": "" - }, - { - "title": "_BIX", - "syntax": "", - "arguments": "", - "description": "Battery Information Extended returns a Control Method Battery extended information block.", - "example": "" - }, - { - "title": "_BLT", - "syntax": "", - "arguments": "", - "description": "Battery Level Threshold set battery level threshold preferences.", - "example": "" - }, - { - "title": "_BM", - "syntax": "", - "arguments": "", - "description": "Bus Master resource descriptor field.", - "example": "" - }, - { - "title": "_BMA", - "syntax": "", - "arguments": "", - "description": "Battery Measurement Averaging Interval Sets battery measurement averaging interval.", - "example": "" - }, - { - "title": "_BMC", - "syntax": "", - "arguments": "", - "description": "Battery Maintenance Control Sets battery maintenance and control features.", - "example": "" - }, - { - "title": "_BMD", - "syntax": "", - "arguments": "", - "description": "Battery Maintenance Data returns battery maintenance, control, and state data.", - "example": "" - }, - { - "title": "_BMS", - "syntax": "", - "arguments": "", - "description": "Battery Measurement Sampling Time Sets the battery measurement sampling time.", - "example": "" - }, - { - "title": "_BQC", - "syntax": "", - "arguments": "", - "description": "Brightness Query Current returns the current display brightness level.", - "example": "" - }, - { - "title": "_BST", - "syntax": "", - "arguments": "", - "description": "Battery Status returns a Control Method Battery status block.\nHeading ", - "example": "" - }, - { - "title": "_BTH", - "syntax": "", - "arguments": "", - "description": "Battery Throttle Limit - specifies the thermal throttle limit of battery for the firmware when engaging charging.", - "example": "" - }, - { - "title": "_BTM", - "syntax": "", - "arguments": "", - "description": "Battery Time returns the battery runtime.", - "example": "" - }, - { - "title": "_BTP", - "syntax": "", - "arguments": "", - "description": "Battery Trip Point sets a Control Method Battery trip point.", - "example": "" - }, - { - "title": "_CBA", - "syntax": "", - "arguments": "", - "description": "Configuration Base Address sets the CBA for a PCI Express host bridge. See the PCI Firmware Specification, Revision 3.0 at \u201cLinks to ACPI-Related Documents\u201d (http://uefi.org/acpi) under the heading \"PCI Sig\".\n ", - "example": "" - }, - { - "title": "_CCA", - "syntax": "", - "arguments": "", - "description": "Cache Coherency Attribute -- specifies whether a device and its descendants support hardware managed cache coherency.", - "example": "" - }, - { - "title": "_CDM", - "syntax": "", - "arguments": "", - "description": "Clock Domain returns a logical processor\u2019s clock domain identifier.", - "example": "" - }, - { - "title": "_CID", - "syntax": "", - "arguments": "", - "description": "Compatible ID returns a device\u2019s Plug and Play Compatible ID list.", - "example": "" - }, - { - "title": "_CLS", - "syntax": "", - "arguments": "", - "description": "Class Code supplies OSPM with the PCI-defined class, subclass and programming interface for a device. Optional.", - "example": "" - }, - { - "title": "_CPC", - "syntax": "", - "arguments": "", - "description": "Continuous Performance Control declares an interface that allows OSPM to transition the processor into a performance state based on a continuous range of allowable values.", - "example": "" - }, - { - "title": "_CRS", - "syntax": "", - "arguments": "", - "description": "Current Resource Settings returns the current resource settings for a device.", - "example": "" - }, - { - "title": "_CRT", - "syntax": "", - "arguments": "", - "description": "Critical Temperature returns the shutdown critical temperature.", - "example": "" - }, - { - "title": "_CSD", - "syntax": "", - "arguments": "", - "description": "C State Dependencies returns a list of C-state dependencies.", - "example": "" - }, - { - "title": "_CST", - "syntax": "", - "arguments": "", - "description": "C States returns a list of supported C-states.", - "example": "" - }, - { - "title": "_CWS", - "syntax": "", - "arguments": "", - "description": "Clear Wake Status Clears the wake status of a Time and Alarm Control Method Device.", - "example": "" - }, - { - "title": "_DBT", - "syntax": "", - "arguments": "", - "description": "Debounce Timeout -Debounce timeout setting for a GPIO input connection, resource descriptor field", - "example": "" - }, - { - "title": "_DCK", - "syntax": "", - "arguments": "", - "description": "Dock sets docking isolation. Presence indicates device is a docking station.", - "example": "" - }, - { - "title": "_DCS", - "syntax": "", - "arguments": "", - "description": "Display Current Status returns status of the display output device.", - "example": "" - }, - { - "title": "_DDC", - "syntax": "", - "arguments": "", - "description": "Display Data Current returns the EDID for the display output device.", - "example": "" - }, - { - "title": "_DDN", - "syntax": "", - "arguments": "", - "description": "Dos Device Name returns a device logical name.", - "example": "" - }, - { - "title": "_DEC", - "syntax": "", - "arguments": "", - "description": "Decode device decoding type, resource descriptor field.", - "example": "" - }, - { - "title": "_DEP", - "syntax": "", - "arguments": "", - "description": "Operation Region Dependencies -- evaluates to a package and designates device objects that OSPM should assign a higher priority in start ordering due to future operation region accesses.", - "example": "" - }, - { - "title": "_DGS", - "syntax": "", - "arguments": "", - "description": "Display Graphics State returns the current state of the output device.", - "example": "" - }, - { - "title": "_DIS", - "syntax": "", - "arguments": "", - "description": "Disable disables a device.", - "example": "" - }, - { - "title": "_DLM", - "syntax": "", - "arguments": "", - "description": "Device Lock Mutex- Designates a mutex as a Device Lock", - "example": "" - }, - { - "title": "_DMA", - "syntax": "", - "arguments": "", - "description": "Direct Memory Access returns a device\u2019s current resources for DMA transactions.\nHeading ", - "example": "" - }, - { - "title": "_DOD", - "syntax": "", - "arguments": "", - "description": "Display Output Devices enumerate all devices attached to the display adapter.", - "example": "" - }, - { - "title": "_DOS", - "syntax": "", - "arguments": "", - "description": "Disable Output Switching sets the display output switching mode.", - "example": "" - }, - { - "title": "_DPL", - "syntax": "", - "arguments": "", - "description": "Device Selection Polarity - The polarity of the Device Selection signal on a SPISerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_DRS", - "syntax": "", - "arguments": "", - "description": "Drive Strength Drive strength setting for a GPIO output connection, resource descriptor field", - "example": "" - }, - { - "title": "_DSD", - "syntax": "", - "arguments": "", - "description": "Device Specific Datareturns device-specific information.", - "example": "" - }, - { - "title": "_DSM", - "syntax": "", - "arguments": "", - "description": "Device Specific Method executes device-specific functions.", - "example": "" - }, - { - "title": "_DSS", - "syntax": "", - "arguments": "", - "description": "Device Set State sets the display device state.", - "example": "" - }, - { - "title": "_DSW", - "syntax": "", - "arguments": "", - "description": "Device Sleep Wake sets the sleep and wake transition states for a device.", - "example": "" - }, - { - "title": "_DTI", - "syntax": "", - "arguments": "", - "description": "Device Temperature Indication conveys native device temperature to the platform.", - "example": "" - }, - { - "title": "_Exx", - "syntax": "", - "arguments": "", - "description": "Edge GPE method executed as a result of a general-purpose event.", - "example": "" - }, - { - "title": "_EC", - "syntax": "", - "arguments": "", - "description": "Embedded Controller returns EC offset and query information.", - "example": "" - }, - { - "title": "_EDL", - "syntax": "", - "arguments": "", - "description": "Eject Device List returns a list of devices that are dependent on a device (docking).", - "example": "" - }, - { - "title": "_EJD", - "syntax": "", - "arguments": "", - "description": "Ejection Dependent Device returns the name of dependent (parent) device (docking).", - "example": "" - }, - { - "title": "_EJx", - "syntax": "", - "arguments": "", - "description": "Eject begin or cancel a device ejection request (docking).", - "example": "" - }, - { - "title": "_END", - "syntax": "", - "arguments": "", - "description": "Endian-ness Endian orientation of a UART SerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_EVT", - "syntax": "", - "arguments": "", - "description": "Event Method - Event method for GPIO-signaled events numbered larger than 255.", - "example": "" - }, - { - "title": "_FDE", - "syntax": "", - "arguments": "", - "description": "Floppy Disk Enumerate returns floppy disk configuration information.", - "example": "" - }, - { - "title": "_FDI", - "syntax": "", - "arguments": "", - "description": "Floppy Drive Information returns a floppy drive information block.", - "example": "" - }, - { - "title": "_FDM", - "syntax": "", - "arguments": "", - "description": "Floppy Drive Mode sets a floppy drive speed.", - "example": "" - }, - { - "title": "_FIF", - "syntax": "", - "arguments": "", - "description": "Fan Information returns fan device information.", - "example": "" - }, - { - "title": "_FIT", - "syntax": "", - "arguments": "", - "description": "Firmware Interface Table - returns a list of NFIT Structures.", - "example": "" - }, - { - "title": "_FIX", - "syntax": "", - "arguments": "", - "description": "Fixed Register Resource Provider returns a list of devices that implement FADT register blocks.", - "example": "" - }, - { - "title": "_FLC", - "syntax": "", - "arguments": "", - "description": "Flow Control Flow Control mechanism for a UART SerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_FPS", - "syntax": "", - "arguments": "", - "description": "Fan Performance States returns a list of supported fan performance states.", - "example": "" - }, - { - "title": "_FSL", - "syntax": "", - "arguments": "", - "description": "Fan Set Level Control method that sets the fan device\u2019s speed level (performance state).\nHeading ", - "example": "" - }, - { - "title": "_FST", - "syntax": "", - "arguments": "", - "description": "Fan Status returns current status information for a fan device.", - "example": "" - }, - { - "title": "_GAI", - "syntax": "", - "arguments": "", - "description": "Get Averaging Interval returns the power meter averaging interval.", - "example": "" - }, - { - "title": "_GCP", - "syntax": "", - "arguments": "", - "description": " Get Capabilities Returns the capabilities of a Time and Alarm Control Method Device", - "example": "" - }, - { - "title": "_GHL", - "syntax": "", - "arguments": "", - "description": "Get Hardware Limit returns the hardware limit enforced by the power meter.", - "example": "" - }, - { - "title": "_GL", - "syntax": "", - "arguments": "", - "description": "Global Lock OS-defined Global Lock mutex object.", - "example": "" - }, - { - "title": "_GLK", - "syntax": "", - "arguments": "", - "description": "Global Lock returns a device\u2019s Global Lock requirement for device access.", - "example": "" - }, - { - "title": "_GPD", - "syntax": "", - "arguments": "", - "description": "Get Post Data returns the value of the VGA device that will be posted at boot.", - "example": "" - }, - { - "title": "_GPE", - "syntax": "", - "arguments": "", - "description": "General Purpose Events (1) predefined Scope (\\_GPE.)\uf020\n(2) Returns the SCI interrupt associated with the Embedded Controller.", - "example": "" - }, - { - "title": "_GRA", - "syntax": "", - "arguments": "", - "description": "Granularity address space granularity, resource descriptor field.", - "example": "" - }, - { - "title": "_GRT", - "syntax": "", - "arguments": "", - "description": " Get Real Time Returns the current time from a Time and Alarm Control Method Device.", - "example": "" - }, - { - "title": "_GSB", - "syntax": "", - "arguments": "", - "description": "Global System Interrupt Base returns the GSB for a I/O APIC device.", - "example": "" - }, - { - "title": "_GTF", - "syntax": "", - "arguments": "", - "description": "Get Task File returns a list of ATA commands to restore a drive to default state.", - "example": "" - }, - { - "title": "_GTM", - "syntax": "", - "arguments": "", - "description": "Get Timing Mode returns a list of IDE controller timing information.", - "example": "" - }, - { - "title": "_GWS", - "syntax": "", - "arguments": "", - "description": "Get Wake Status Gets the wake status of a Time and Alarm Control Method Device.", - "example": "" - }, - { - "title": "_HE", - "syntax": "", - "arguments": "", - "description": "High-Edge interrupt triggering, resource descriptor field.", - "example": "" - }, - { - "title": "_HID", - "syntax": "", - "arguments": "", - "description": "Hardware ID returns a device\u2019s Plug and Play Hardware ID.", - "example": "" - }, - { - "title": "_HMA", - "syntax": "", - "arguments": "", - "description": "Heterogeneous Memory Attributes - returns a list of HMAT structures.", - "example": "" - }, - { - "title": "_HOT", - "syntax": "", - "arguments": "", - "description": "Hot Temperature returns the critical temperature for sleep (entry to S4).", - "example": "" - }, - { - "title": "_HPP", - "syntax": "", - "arguments": "", - "description": "Hot Plug Parameters returns a list of hot-plug information for a PCI device.", - "example": "" - }, - { - "title": "_HPX", - "syntax": "", - "arguments": "", - "description": "Hot Plug Parameter Extensions returns a list of hot-plug information for a PCI device. Supersedes _HPP.", - "example": "" - }, - { - "title": "_HRV", - "syntax": "", - "arguments": "", - "description": "Hardware Revisionsupplies OSPM with the device\u2019s hardware revision. Optional", - "example": "" - }, - { - "title": "_IFT", - "syntax": "", - "arguments": "", - "description": "IPMI Interface Type. See the Intelligent Platform Management Interface Specification at \u201cLinks to ACPI-Related Documents\u201d (http://uefi.org/acpi) under the heading \"Server Platform Management Interface Table\".", - "example": "" - }, - { - "title": "_INI", - "syntax": "", - "arguments": "", - "description": "Initialize performs device specific initialization.", - "example": "" - }, - { - "title": "_INT", - "syntax": "", - "arguments": "", - "description": "Interrupts interrupt mask bits, resource descriptor field.\nHeading ", - "example": "" - }, - { - "title": "_IOR", - "syntax": "", - "arguments": "", - "description": "IO Restriction IO restriction setting for a GPIO IO connection, resource descriptor field", - "example": "" - }, - { - "title": "_IRC", - "syntax": "", - "arguments": "", - "description": "Inrush Current presence indicates that a device has a significant inrush current draw.", - "example": "" - }, - { - "title": "_Lxx", - "syntax": "", - "arguments": "", - "description": "Level GPE Control method executed as a result of a general-purpose event.", - "example": "" - }, - { - "title": "_LCK", - "syntax": "", - "arguments": "", - "description": "Lock locks or unlocks a device (docking).", - "example": "" - }, - { - "title": "_LEN", - "syntax": "", - "arguments": "", - "description": "Length range length, resource descriptor field.", - "example": "" - }, - { - "title": "_LID", - "syntax": "", - "arguments": "", - "description": "Lid returns the open/closed status of the lid on a mobile system.", - "example": "" - }, - { - "title": "_LIN", - "syntax": "", - "arguments": "", - "description": "Lines in Use - Handshake lines in use in a UART SerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_LL", - "syntax": "", - "arguments": "", - "description": "Low Level interrupt polarity, resource descriptor field.", - "example": "" - }, - { - "title": "_LPI", - "syntax": "", - "arguments": "", - "description": "Low Power Idle States returns the list of low power idle states supported by a processor or processor container.", - "example": "" - }, - { - "title": "_LSI", - "syntax": "", - "arguments": "", - "description": "Label Storage Information Returns information about the Label Storage Area associated with the NVDIMM object, including its size.", - "example": "" - }, - { - "title": "_LSR", - "syntax": "", - "arguments": "", - "description": "Label Storage Read Returns label data from the Label Storage Area of the NVDIMM object.", - "example": "" - }, - { - "title": "_LSW", - "syntax": "", - "arguments": "", - "description": "Label Storage Write Writes label data in to the Label Storage Area of the NVDIMM object.", - "example": "" - }, - { - "title": "_MAF", - "syntax": "", - "arguments": "", - "description": "Maximum Address Fixed resource descriptor field.", - "example": "" - }, - { - "title": "_MAT", - "syntax": "", - "arguments": "", - "description": "Multiple Apic Table Entry returns a list of Interrupt Controller Structures.", - "example": "" - }, - { - "title": "_MAX", - "syntax": "", - "arguments": "", - "description": "Maximum Base Address resource descriptor field.", - "example": "" - }, - { - "title": "_MBM", - "syntax": "", - "arguments": "", - "description": "Memory Bandwidth Monitoring Data returns bandwidth monitoring data for a memory device.", - "example": "" - }, - { - "title": "_MEM", - "syntax": "", - "arguments": "", - "description": "Memory Attributes resource descriptor field.", - "example": "" - }, - { - "title": "_MIF", - "syntax": "", - "arguments": "", - "description": "Minimum Address Fixed resource descriptor field.", - "example": "" - }, - { - "title": "_MIN", - "syntax": "", - "arguments": "", - "description": "Minimum Base Address resource descriptor field.", - "example": "" - }, - { - "title": "_MLS", - "syntax": "", - "arguments": "", - "description": "Multiple Language String returns a device description in multiple languages.", - "example": "" - }, - { - "title": "_MOD", - "syntax": "", - "arguments": "", - "description": "Mode \u2013Resource descriptor field", - "example": "" - }, - { - "title": "_MSG", - "syntax": "", - "arguments": "", - "description": "Message sets the system message waiting status indicator.", - "example": "" - }, - { - "title": "_MSM", - "syntax": "", - "arguments": "", - "description": "Memory Set Monitoring sets bandwidth monitoring parameters for a memory device.", - "example": "" - }, - { - "title": "_MTL", - "syntax": "", - "arguments": "", - "description": "Minimum Throttle Limit returns the minimum throttle limit of a specific thermal", - "example": "" - }, - { - "title": "_MTP", - "syntax": "", - "arguments": "", - "description": "Memory Type resource descriptor field.\nHeading ", - "example": "" - }, - { - "title": "_NTT", - "syntax": "", - "arguments": "", - "description": "Notification Temperature Threshold returns a threshold for device temperature change that requires platform notification.", - "example": "" - }, - { - "title": "_OFF", - "syntax": "", - "arguments": "", - "description": "Off sets a power resource to the off state.", - "example": "" - }, - { - "title": "_ON", - "syntax": "", - "arguments": "", - "description": "On sets a power resource to the on state.", - "example": "" - }, - { - "title": "_OS", - "syntax": "", - "arguments": "", - "description": "Operating System returns a string that identifies the operating system.", - "example": "" - }, - { - "title": "_OSC", - "syntax": "", - "arguments": "", - "description": "Operating System Capabilities inform AML of host features and capabilities.", - "example": "" - }, - { - "title": "_OSI", - "syntax": "", - "arguments": "", - "description": "Operating System Interfaces returns supported interfaces, behaviors, and features.", - "example": "" - }, - { - "title": "_OST", - "syntax": "", - "arguments": "", - "description": "Ospm Status Indication inform AML of event processing status.", - "example": "" - }, - { - "title": "_PAI", - "syntax": "", - "arguments": "", - "description": "Power Averaging Interval sets the averaging interval for a power meter.", - "example": "" - }, - { - "title": "_PAR", - "syntax": "", - "arguments": "", - "description": "Parity Parity for a UART SerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_PCL", - "syntax": "", - "arguments": "", - "description": "Power Consumer List returns a list of devices powered by a power source.", - "example": "" - }, - { - "title": "_PCT", - "syntax": "", - "arguments": "", - "description": "Performance Control returns processor performance control and status registers.", - "example": "" - }, - { - "title": "_PDC", - "syntax": "", - "arguments": "", - "description": "Processor Driver Capabilities inform AML of processor driver capabilities.", - "example": "" - }, - { - "title": "_PDL", - "syntax": "", - "arguments": "", - "description": "P-state Depth Limit returns the lowest available performance P-state.", - "example": "" - }, - { - "title": "_PHA", - "syntax": "", - "arguments": "", - "description": "Clock Phase Clock phase for a SPISerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_PIC", - "syntax": "", - "arguments": "", - "description": "PIC inform AML of the interrupt model in use.", - "example": "" - }, - { - "title": "_PIF", - "syntax": "", - "arguments": "", - "description": "Power Source Information returns a Power Source information block.", - "example": "" - }, - { - "title": "_PIN", - "syntax": "", - "arguments": "", - "description": " Pin List List of GPIO pins described, resource descriptor field.", - "example": "" - }, - { - "title": "_PLD", - "syntax": "", - "arguments": "", - "description": "Physical Location of Device returns a device\u2019s physical location information.", - "example": "" - }, - { - "title": "_PMC", - "syntax": "", - "arguments": "", - "description": "Power Meter Capabilities returns a list of Power Meter capabilities info.", - "example": "" - }, - { - "title": "_PMD", - "syntax": "", - "arguments": "", - "description": "Power Metered Devices returns a list of devices that are measured by the power meter device.", - "example": "" - }, - { - "title": "_PMM", - "syntax": "", - "arguments": "", - "description": "Power Meter Measurement returns the current value of the Power Meter.", - "example": "" - }, - { - "title": "_POL", - "syntax": "", - "arguments": "", - "description": "Polarity Resource descriptor field", - "example": "" - }, - { - "title": "_PPC", - "syntax": "", - "arguments": "", - "description": "Performance Present Capabilites returns a list of the performance states currently supported by the platform.", - "example": "" - }, - { - "title": "_PPE", - "syntax": "", - "arguments": "", - "description": "Polling for Platform Error returns the polling interval to retrieve Corrected Platform Error information.", - "example": "" - }, - { - "title": "_PPI", - "syntax": "", - "arguments": "", - "description": "Pin Configuration Pin configuration for a GPIO connection, resource descriptor field\nHeading ", - "example": "" - }, - { - "title": "_PR", - "syntax": "", - "arguments": "", - "description": "Processor predefined scope for processor objects.", - "example": "" - }, - { - "title": "_PR0", - "syntax": "", - "arguments": "", - "description": "Power Resources for D0 returns a list of dependent power resources to enter state D0 (fully on).", - "example": "" - }, - { - "title": "_PR1", - "syntax": "", - "arguments": "", - "description": "Power Resources for D1 returns a list of dependent power resources to enter state D1.", - "example": "" - }, - { - "title": "_PR2", - "syntax": "", - "arguments": "", - "description": "Power Resources for D2 returns a list of dependent power resources to enter state D2.", - "example": "" - }, - { - "title": "_PR3", - "syntax": "", - "arguments": "", - "description": "Power Resources for D3hot returns a list of dependent power resources to enter state D3hot.", - "example": "" - }, - { - "title": "_PRE", - "syntax": "", - "arguments": "", - "description": "Power Resources for Enumeration - Returns a list of dependent power resources to enumerate devices on a bus.", - "example": "" - }, - { - "title": "_PRL", - "syntax": "", - "arguments": "", - "description": "Power Source Redundancy List returns a list of power source devices in the same redundancy grouping.", - "example": "" - }, - { - "title": "_PRR", - "syntax": "", - "arguments": "", - "description": "Power Resource for Reset executes a reset on the associated device or devices.", - "example": "" - }, - { - "title": "_PRS", - "syntax": "", - "arguments": "", - "description": "Possible Resource Settings returns a list of a device\u2019s possible resource settings.", - "example": "" - }, - { - "title": "_PRT", - "syntax": "", - "arguments": "", - "description": "Pci Routing Table returns a list of PCI interrupt mappings.", - "example": "" - }, - { - "title": "_PRW", - "syntax": "", - "arguments": "", - "description": "Power Resources for Wake returns a list of dependent power resources for waking.", - "example": "" - }, - { - "title": "_PS0", - "syntax": "", - "arguments": "", - "description": "Power State 0 sets a device\u2019s power state to D0 (device fully on).", - "example": "" - }, - { - "title": "_PS1", - "syntax": "", - "arguments": "", - "description": "Power State 1 sets a device\u2019s power state to D1.", - "example": "" - }, - { - "title": "_PS2", - "syntax": "", - "arguments": "", - "description": "Power State 2 sets a device\u2019s power state to D2.", - "example": "" - }, - { - "title": "_PS3", - "syntax": "", - "arguments": "", - "description": "Power State 3 sets a device\u2019s power state to D3 (device off).", - "example": "" - }, - { - "title": "_PSC", - "syntax": "", - "arguments": "", - "description": "Power State Current returns a device\u2019s current power state.", - "example": "" - }, - { - "title": "_PSD", - "syntax": "", - "arguments": "", - "description": "Power State Dependencies returns processor P-State dependencies.", - "example": "" - }, - { - "title": "_PSE", - "syntax": "", - "arguments": "", - "description": "Power State for Enumeration", - "example": "" - }, - { - "title": "_PSL", - "syntax": "", - "arguments": "", - "description": "Passive List returns a list of passive cooling device objects.", - "example": "" - }, - { - "title": "_PSR", - "syntax": "", - "arguments": "", - "description": "Power Source returns the power source device currently in use.", - "example": "" - }, - { - "title": "_PSS", - "syntax": "", - "arguments": "", - "description": "Performance Supported States returns a list of supported processor performance states.", - "example": "" - }, - { - "title": "_PSV", - "syntax": "", - "arguments": "", - "description": "Passive returns the passive trip point temperature.", - "example": "" - }, - { - "title": "_PSW", - "syntax": "", - "arguments": "", - "description": "Power State Wake sets a device\u2019s wake function.", - "example": "" - }, - { - "title": "_PTC", - "syntax": "", - "arguments": "", - "description": "Processor Throttling Control returns throttling control and status registers.", - "example": "" - }, - { - "title": "_PTP", - "syntax": "", - "arguments": "", - "description": "Power Trip Points sets trip points for the Power Meter device.", - "example": "" - }, - { - "title": "_PTS", - "syntax": "", - "arguments": "", - "description": "Prepare To Sleep inform the platform of an impending sleep transition.\nHeading ", - "example": "" - }, - { - "title": "_PUR", - "syntax": "", - "arguments": "", - "description": "Processor Utilization Request returns the number of processors that the platform would like to idle.", - "example": "" - }, - { - "title": "_PXM", - "syntax": "", - "arguments": "", - "description": "Proximity returns a device\u2019s proximity domain identifier.", - "example": "" - }, - { - "title": "_Qxx", - "syntax": "", - "arguments": "", - "description": "Query Embedded Controller query and SMBus Alarm control method.", - "example": "" - }, - { - "title": "_RBO", - "syntax": "", - "arguments": "", - "description": "Register Bit Offset resource descriptor field.", - "example": "" - }, - { - "title": "_RBW", - "syntax": "", - "arguments": "", - "description": "Register Bit Width resource descriptor field.", - "example": "" - }, - { - "title": "_RDI", - "syntax": "", - "arguments": "", - "description": "Resource Dependencies for Idle - returns the list of power resource dependencies for system level low power idle states.", - "example": "" - }, - { - "title": "_REG", - "syntax": "", - "arguments": "", - "description": "Region inform AML code of an operation region availability change.", - "example": "" - }, - { - "title": "_REV", - "syntax": "", - "arguments": "", - "description": "Revision returns the revision of the ACPI specification that is implemented.", - "example": "" - }, - { - "title": "_RMV", - "syntax": "", - "arguments": "", - "description": "Remove returns a device\u2019s removal ability status (docking).", - "example": "" - }, - { - "title": "_RNG", - "syntax": "", - "arguments": "", - "description": "Range memory range type, resource descriptor field.", - "example": "" - }, - { - "title": "_ROM", - "syntax": "", - "arguments": "", - "description": "Read-Only Memory returns a copy of the ROM data for a display device.", - "example": "" - }, - { - "title": "_RST", - "syntax": "", - "arguments": "", - "description": "Device Reset executes a reset on the associated device or devices.", - "example": "" - }, - { - "title": "_RT", - "syntax": "", - "arguments": "", - "description": "Resource Type resource descriptor field.", - "example": "" - }, - { - "title": "_RTV", - "syntax": "", - "arguments": "", - "description": "Relative Temperature Values returns temperature value information.", - "example": "" - }, - { - "title": "_RW", - "syntax": "", - "arguments": "", - "description": "Read-Write Status resource descriptor field.", - "example": "" - }, - { - "title": "_RXL", - "syntax": "", - "arguments": "", - "description": "Receive Buffer Size - Size of the receive buffer in a UART Serialbus connection, resource descriptor field.", - "example": "" - }, - { - "title": "_S0", - "syntax": "", - "arguments": "", - "description": "S0 System State returns values to enter the system into the S0 state.", - "example": "" - }, - { - "title": "_S1", - "syntax": "", - "arguments": "", - "description": "S1 System State returns values to enter the system into the S1 state.", - "example": "" - }, - { - "title": "_S2", - "syntax": "", - "arguments": "", - "description": "S2 System State returns values to enter the system into the S2 state.", - "example": "" - }, - { - "title": "_S3", - "syntax": "", - "arguments": "", - "description": "S3 System State returns values to enter the system into the S3 state.", - "example": "" - }, - { - "title": "_S4", - "syntax": "", - "arguments": "", - "description": "S4 System State returns values to enter the system into the S4 state.", - "example": "" - }, - { - "title": "_S5", - "syntax": "", - "arguments": "", - "description": "S5 System State returns values to enter the system into the S5 state.", - "example": "" - }, - { - "title": "_S1D", - "syntax": "", - "arguments": "", - "description": "S1 Device State returns the highest D-state supported by a device when in the S1 state.", - "example": "" - }, - { - "title": "_S2D", - "syntax": "", - "arguments": "", - "description": "S2 Device State returns the highest D-state supported by a device when in the S2 state.", - "example": "" - }, - { - "title": "_S3D", - "syntax": "", - "arguments": "", - "description": "S3 Device State returns the highest D-state supported by a device when in the S3 state.", - "example": "" - }, - { - "title": "_S4D", - "syntax": "", - "arguments": "", - "description": "S4 Device State returns the highest D-state supported by a device when in the S4 state.", - "example": "" - }, - { - "title": "_S0W", - "syntax": "", - "arguments": "", - "description": "S0 Device Wake State returns the lowest D-state that the device can wake itself from S0.\nHeading ", - "example": "" - }, - { - "title": "_S1W", - "syntax": "", - "arguments": "", - "description": "S1 Device Wake State returns the lowest D-state for this device that can wake the system from S1.", - "example": "" - }, - { - "title": "_S2W", - "syntax": "", - "arguments": "", - "description": "S2 Device Wake State returns the lowest D-state for this device that can wake the system from S2.", - "example": "" - }, - { - "title": "_S3W", - "syntax": "", - "arguments": "", - "description": "S3 Device Wake State returns the lowest D-state for this device that can wake the system from S3.", - "example": "" - }, - { - "title": "_S4W", - "syntax": "", - "arguments": "", - "description": "S4 Device Wake State returns the lowest D-state for this device that can wake the system from S4.", - "example": "" - }, - { - "title": "_SB", - "syntax": "", - "arguments": "", - "description": "System Bus scope for device and bus objects.", - "example": "" - }, - { - "title": "_SBS", - "syntax": "", - "arguments": "", - "description": "Smart Battery Subsystem returns the subsystem configuration.", - "example": "" - }, - { - "title": "_SCP", - "syntax": "", - "arguments": "", - "description": "Set Cooling Policy sets the cooling policy (active or passive).", - "example": "" - }, - { - "title": "_SDD", - "syntax": "", - "arguments": "", - "description": "Set Device Data sets data for a SATA device.", - "example": "" - }, - { - "title": "_SEG", - "syntax": "", - "arguments": "", - "description": "Segment returns a device\u2019s PCI Segment Group number.", - "example": "" - }, - { - "title": "_SHL", - "syntax": "", - "arguments": "", - "description": "Set Hardware Limit sets the hardware limit enforced by the Power Meter.", - "example": "" - }, - { - "title": "_SHR", - "syntax": "", - "arguments": "", - "description": "Sharable interrupt share status, resource descriptor field.", - "example": "" - }, - { - "title": "_SI", - "syntax": "", - "arguments": "", - "description": "System Indicators predefined scope.", - "example": "" - }, - { - "title": "_SIZ", - "syntax": "", - "arguments": "", - "description": "Size DMA transfer size, resource descriptor field.", - "example": "" - }, - { - "title": "_SLI", - "syntax": "", - "arguments": "", - "description": "System Locality Information returns a list of NUMA system localities.", - "example": "" - }, - { - "title": "_SLV", - "syntax": "", - "arguments": "", - "description": "Slave Mode Slave mode setting for a SerialBus connection, resource descriptor field.", - "example": "" - }, - { - "title": "_SPD", - "syntax": "", - "arguments": "", - "description": "Set Post Device sets which video device will be posted at boot.", - "example": "" - }, - { - "title": "_SPE", - "syntax": "", - "arguments": "", - "description": "Connection Speed Connection speed for a SerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_SRS", - "syntax": "", - "arguments": "", - "description": "Set Resource Settings sets a device\u2019s resource allocation.", - "example": "" - }, - { - "title": "_SRT", - "syntax": "", - "arguments": "", - "description": "Set Real Time Sets the current time to a Time and Alarm Control Method Device.", - "example": "" - }, - { - "title": "_SRV", - "syntax": "", - "arguments": "", - "description": "IPMI Spec Revision. See the Intelligent Platform Management Interface Specification at \u201cLinks to ACPI-Related Documents\u201d (http://uefi.org/acpi) under the heading \"Server Platform Management Interface Table\".\n ", - "example": "" - }, - { - "title": "_SST", - "syntax": "", - "arguments": "", - "description": "System Status sets the system status indicator.", - "example": "" - }, - { - "title": "_STA", - "syntax": "", - "arguments": "", - "description": "Status (1) returns the current status of a device.\uf020\n(2) Returns the current on or off state of a Power Resource.", - "example": "" - }, - { - "title": "_STB", - "syntax": "", - "arguments": "", - "description": "Stop Bits - Number of stop bits used in a UART SerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_STM", - "syntax": "", - "arguments": "", - "description": "Set Timing Mode sets an IDE controller transfer timings.\nHeading ", - "example": "" - }, - { - "title": "_STP", - "syntax": "", - "arguments": "", - "description": "Set Expired Timer Wake Policy sets expired timer policies of the wake alarm device.", - "example": "" - }, - { - "title": "_STR", - "syntax": "", - "arguments": "", - "description": "String returns a device\u2019s description string.", - "example": "" - }, - { - "title": "_STV", - "syntax": "", - "arguments": "", - "description": "Set Timer Value set timer values of the wake alarm device.", - "example": "" - }, - { - "title": "_SUB", - "syntax": "", - "arguments": "", - "description": "Supplies OSPM with the device's Subsystem ID. Optional.", - "example": "" - }, - { - "title": "_SUN", - "syntax": "", - "arguments": "", - "description": "Slot User Number returns the slot unique ID number.", - "example": "" - }, - { - "title": "_SWS", - "syntax": "", - "arguments": "", - "description": "System Wake Source returns the source event that caused the system to wake.", - "example": "" - }, - { - "title": "_T_x", - "syntax": "", - "arguments": "", - "description": "Temporary reserved for use by ASL compilers.", - "example": "" - }, - { - "title": "_TC1", - "syntax": "", - "arguments": "", - "description": "Thermal Constant 1 returns TC1 for the passive cooling formula.", - "example": "" - }, - { - "title": "_TC2", - "syntax": "", - "arguments": "", - "description": "Thermal Constant 2 returns TC2 for the passive cooling formula.", - "example": "" - }, - { - "title": "_TDL", - "syntax": "", - "arguments": "", - "description": "T-State Depth Limit returns the _TSS entry number of the lowest power throttling state.", - "example": "" - }, - { - "title": "_TFP", - "syntax": "", - "arguments": "", - "description": "Thermal Fast Sampling Period - returns the thermal sampling period for passive cooling.", - "example": "" - }, - { - "title": "_TIP", - "syntax": "", - "arguments": "", - "description": "Expired Timer Wake Policy returns timer policies of the wake alarm device.", - "example": "" - }, - { - "title": "_TIV", - "syntax": "", - "arguments": "", - "description": "Timer Values returns remaining time of the wake alarm device.", - "example": "" - }, - { - "title": "_TMP", - "syntax": "", - "arguments": "", - "description": "Temperature returns a thermal zone\u2019s current temperature.", - "example": "" - }, - { - "title": "_TPC", - "syntax": "", - "arguments": "", - "description": "Throttling Present Capabilities returns the current number of supported throttling states.", - "example": "" - }, - { - "title": "_TPT", - "syntax": "", - "arguments": "", - "description": "Trip Point Temperature inform AML that a devices\u2019 embedded temperature sensor has crossed a temperature trip point.", - "example": "" - }, - { - "title": "_TRA", - "syntax": "", - "arguments": "", - "description": "Translation address translation offset, resource descriptor field.", - "example": "" - }, - { - "title": "_TRS", - "syntax": "", - "arguments": "", - "description": "Translation Sparse sparse/dense flag, resource descriptor field.", - "example": "" - }, - { - "title": "_TRT", - "syntax": "", - "arguments": "", - "description": "Thermal Relationship Table returns thermal relationships between platform devices.", - "example": "" - }, - { - "title": "_TSD", - "syntax": "", - "arguments": "", - "description": "Throttling State Dependencies returns a list of T-state dependencies.", - "example": "" - }, - { - "title": "_TSF", - "syntax": "", - "arguments": "", - "description": "Type-Specific Flags resource descriptor field.", - "example": "" - }, - { - "title": "_TSN", - "syntax": "", - "arguments": "", - "description": "Thermal Sensor Device - returns a reference to the thermal sensor reporting a zone temperature", - "example": "" - }, - { - "title": "_TSP", - "syntax": "", - "arguments": "", - "description": "Thermal Sampling Period returns the thermal sampling period for passive cooling.", - "example": "" - }, - { - "title": "_TSS", - "syntax": "", - "arguments": "", - "description": "Throttling Supported States returns supported throttling state information.", - "example": "" - }, - { - "title": "_TST", - "syntax": "", - "arguments": "", - "description": "Temperature Sensor Threshold returns the minimum separation for a device\u2019s temperature trip points.", - "example": "" - }, - { - "title": "_TTP", - "syntax": "", - "arguments": "", - "description": "Translation Type translation/static flag, resource descriptor field.\nHeading ", - "example": "" - }, - { - "title": "_TTS", - "syntax": "", - "arguments": "", - "description": "Transition To State inform AML of an S-state transition.", - "example": "" - }, - { - "title": "_TXL", - "syntax": "", - "arguments": "", - "description": "Transmit Buffer Size Size of the transmit buffer in a UART Serialbus connection, resource descriptor field", - "example": "" - }, - { - "title": "_TYP", - "syntax": "", - "arguments": "", - "description": "Type DMA channel type (speed), resource descriptor field.", - "example": "" - }, - { - "title": "_TZ", - "syntax": "", - "arguments": "", - "description": "Thermal Zone predefined scope: ACPI 1.0.", - "example": "" - }, - { - "title": "_TZD", - "syntax": "", - "arguments": "", - "description": "Thermal Zone Devices returns a list of device names associated with a Thermal Zone.", - "example": "" - }, - { - "title": "_TZM", - "syntax": "", - "arguments": "", - "description": "Thermal Zone Member returns a reference to the thermal zone of which a device is a member.", - "example": "" - }, - { - "title": "_TZP", - "syntax": "", - "arguments": "", - "description": "Thermal Zone Polling returns a Thermal zone\u2019s polling frequency.", - "example": "" - }, - { - "title": "_UID", - "syntax": "", - "arguments": "", - "description": "Unique ID return a device\u2019s unique persistent ID.", - "example": "" - }, - { - "title": "_UPC", - "syntax": "", - "arguments": "", - "description": "USB Port Capabilities returns a list of USB port capabilities.", - "example": "" - }, - { - "title": "_UPD", - "syntax": "", - "arguments": "", - "description": "User Presence Detect returns user detection information.", - "example": "" - }, - { - "title": "_UPP", - "syntax": "", - "arguments": "", - "description": "User Presence Polling returns the recommended user presence polling interval.", - "example": "" - }, - { - "title": "_VEN", - "syntax": "", - "arguments": "", - "description": "Vendor-defined Data Vendor-defined data for a GPIO or SerialBus connection, resource descriptor field", - "example": "" - }, - { - "title": "_VPO", - "syntax": "", - "arguments": "", - "description": "Video Post Options returns the implemented video post options.", - "example": "" - }, - { - "title": "_WAK", - "syntax": "", - "arguments": "", - "description": "Wake inform AML that the system has just awakened.", - "example": "" - }, - { - "title": "_WPC", - "syntax": "", - "arguments": "", - "description": "Wireless Power Calibration - returns the notifier to wireless power controller", - "example": "" - }, - { - "title": "_WPP", - "syntax": "", - "arguments": "", - "description": "Wireless Power Polling - returns the recommended polling frequency", - "example": "" - } -] \ No newline at end of file diff --git a/static/buildForm.html b/static/buildForm.html deleted file mode 100644 index 3e4cddb..0000000 --- a/static/buildForm.html +++ /dev/null @@ -1,681 +0,0 @@ - - - - - -EDK2 Build Configuration - - - - - -
- - - - - -
-

- EDK2 Build Configuration -

-

Configure build arguments, then click Build. Settings for individual modules are saved automatically.

- -
- ⚠️ Beta Feature: Build arguments were automatically calculated from your workspace configuration but may need manual adjustments. Please review before building. -
- - -

Target

-
- - - - - - - - - - - - - - - - - - - -
- - -

Common Options

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -

Flags

-
- - - - - - - - - - - - - - -
- - -

Report

-
- - - - -
-
- - -

Binary Cache

-
- - - - - -
- - -

Defines (-D)

-

Macro definitions passed as -D Name=Value.

-
- - - -

PCDs (--pcd)

-

PCD overrides passed as --pcd=PcdName=Value.

-
- - - -

Extra Arguments

-

Additional arguments passed verbatim to build.

-
- - - -

Environment

-
- -
-
- - - -

Global Configuration

-

These settings are shared across all builds and saved globally in .edkCode/edk2_build_configuration.json.

-
- - - - - - - - - - - - - - -
- -
- - -
-
-
-

Building...

-
-
- - - - diff --git a/static/cscope.exe b/static/cscope.exe deleted file mode 100644 index 035abfb..0000000 Binary files a/static/cscope.exe and /dev/null differ diff --git a/static/jquery.min.js b/static/jquery.min.js deleted file mode 100644 index 0de648e..0000000 --- a/static/jquery.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.4 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.4",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.cssHas=ce(function(){try{return C.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),d.cssHas||y.push(":has"),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType&&e.documentElement||e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 $(VAR8) - # !error "VAR5 is less than VAR6 or VAR7 is greater than VAR8" -!else - !error "VAR5 is not less than VAR6 and VAR7 is not greater than VAR8" -!endif - -!if $(VAR9) <= $(VAR10) && $(VAR11) >= $(VAR12) - # !error "VAR9 is less than or equal to VAR10 and VAR11 is greater than or equal to VAR12" -!else - !error "VAR9 is not less than or equal to VAR10 or VAR11 is not greater than or equal to VAR12" -!endif - -!if $(VAR17) * $(VAR18) == $(VAR19) / $(VAR20) - # !error "Multiplication and division result in equality" -!else - !error "Multiplication and division do not result in equality" -!endif - -!if $(VAR21) % $(VAR22) == 0 - # !error "VAR21 is divisible by VAR22" -!else - !error "VAR21 is not divisible by VAR22" -!endif - -!if ~$(VAR23) == $(VAR24) - !error "Bitwise NOT of VAR23 equals VAR24" -!else - # !error "Bitwise NOT of VAR23 does not equal VAR24" -!endif - -!if $(VAR25) << 1 == $(VAR26) >> 1 - !error "Left shift of VAR25 equals right shift of VAR26" -!else - # !error "Left shift of VAR25 does not equal right shift of VAR26" -!endif - -!error "ALL Test Passed" \ No newline at end of file diff --git a/test/testDscParsing.dsc b/test/testDscParsing.dsc deleted file mode 100644 index b3139dc..0000000 --- a/test/testDscParsing.dsc +++ /dev/null @@ -1,63 +0,0 @@ -## Corner-case DSC file used by the parser unit tests. -## Every section exercises a different parsing path. - -[Defines] - PLATFORM_NAME = TestParsing - PLATFORM_GUID = AABBCCDD-1122-3344-5566-778899AABBCC - PLATFORM_VERSION = 0.1 - DSC_SPECIFICATION = 0x00010017 - OUTPUT_DIRECTORY = Build/TestParsing - SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64 - BUILD_TARGETS = DEBUG|RELEASE - DEFINE MY_VAR = SomeValue - DEFINE EMPTY_VAR = - -# Root-level define (outside any section) -DEFINE ROOT_DEFINE = OutsideSection - -[SkuIds] - 0|DEFAULT - -[LibraryClasses] - BaseLib | MdePkg/Library/BaseLib/BaseLib.inf - DebugLib|MdePkg/Library/DebugLib/DebugLib.inf - # Library with spaces around pipe - PrintLib | MdePkg/Library/PrintLib/PrintLib.inf - -[LibraryClasses.X64] - TimerLib|MdePkg/Library/TimerLib/TimerLib.inf - -[Components] - MdePkg/Test/SimpleModule.inf - MdePkg/Test/AnotherModule.inf - -[Components.X64] - # Module with sub-sections - MdePkg/Test/ComplexModule.inf { - - BaseLib | MdePkg/Library/OverrideLib/Override.inf - - gTokenSpace.PcdFoo|0x1 - - MSFT:*_*_*_CC_FLAGS = /DTEST - } - - # Module without braces - MdePkg/Test/PlainModule.inf - -[PcdsFixedAtBuild] - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F - gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000040 - -[PcdsDynamicDefault] - gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|5 - -[BuildOptions] - GCC:*_*_*_CC_FLAGS = -DMDEPKG_NDEBUG - MSFT:*_*_*_CC_FLAGS = /DMDEPKG_NDEBUG - # Comment inside build options - -!include TestInclude.dsc.inc - -/* Block comment test */ -# End of file diff --git a/test/testDscProcess.dsc b/test/testDscProcess.dsc deleted file mode 100644 index b9b7926..0000000 --- a/test/testDscProcess.dsc +++ /dev/null @@ -1,85 +0,0 @@ -[Defines] - PLATFORM_NAME = TestProcess - PLATFORM_GUID = 11111111-2222-3333-4444-555555555555 - PLATFORM_VERSION = 2.0 - DSC_SPECIFICATION = 0x00010017 - DEFINE MY_FLAG = TRUE - DEFINE MY_PATH = SomePath - DEFINE EMPTY_DEF = - -# Root-level define -DEFINE ROOT_DEF = RootValue - -# Test that comments are stripped -# This line is a comment and should not appear - -[SkuIds] - 0|DEFAULT - -[LibraryClasses] - BaseLib|MdePkg/Library/BaseLib/BaseLib.inf - DebugLib|MdePkg/Library/DebugLib/DebugLib.inf - -[LibraryClasses.X64] - TimerLib|MdePkg/Library/TimerLib/TimerLib.inf - -[Components] - MdePkg/Test/ModuleA.inf - MdePkg/Test/ModuleB.inf - -[Components.X64] - MdePkg/Test/ModuleC.inf - -[PcdsFixedAtBuild] - gTestPkg.PcdTestMask|0x2F - gTestPkg.PcdTestLevel|0x80000040 - -[PcdsDynamicDefault] - gTestPkg.PcdBootTimeout|5 - -[BuildOptions] - GCC:*_*_*_CC_FLAGS = -DTEST - MSFT:*_*_*_CC_FLAGS = /DTEST - -# Conditional block test: TRUE branch taken -DEFINE COND_A = BeforeIf -!if TRUE - DEFINE COND_TAKEN = IfTrueValue -!else - DEFINE COND_TAKEN = IfFalseValue -!endif - -# Conditional block test: FALSE branch -> else taken -!if FALSE - DEFINE COND_FALSE_IF = ShouldNotExist -!else - DEFINE COND_ELSE = ElseValue -!endif - -# Nested conditional -!if TRUE - DEFINE OUTER_TRUE = OuterOk - !if FALSE - DEFINE INNER_FALSE = ShouldNotExist - !else - DEFINE INNER_ELSE = InnerElseOk - !endif -!endif - -# !ifdef test -DEFINE EXISTING_VAR = Exists -!ifdef EXISTING_VAR - DEFINE IFDEF_TAKEN = yes -!endif - -# !ifndef test on undefined variable -!ifndef TOTALLY_UNDEFINED_XYZ - DEFINE IFNDEF_TAKEN = yes -!endif - -# Define with variable reference -DEFINE BASE = Hello -DEFINE DERIVED = $(BASE)World - -# PCD in string value - gTestPkg.PcdStringVal|L"TestString" diff --git a/test/testFdfParsing.fdf b/test/testFdfParsing.fdf deleted file mode 100644 index a846a5a..0000000 --- a/test/testFdfParsing.fdf +++ /dev/null @@ -1,38 +0,0 @@ -## Corner-case FDF file for parser tests. - -[FD.TestFd] - BaseAddress = 0xFF000000 - Size = 0x01000000 - ErasePolarity = 1 - BlockSize = 0x00010000 - NumBlocks = 0x100 - - DEFINE FD_VAR = SomeValue - -[FV.FVMAIN] - FvAlignment = 16 - ERASE_POLARITY = 1 - MEMORY_MAPPED = TRUE - - INF MdePkg/Test/SimpleModule.inf - INF MdePkg/Test/AnotherModule.inf - - DEFINE FV_VAR = AnotherValue - -[FV.FVRECOVERY] - FvAlignment = 16 - - APRIORI DXE { - INF MdePkg/Test/AprioriModule.inf - } - - INF MdePkg/Test/RecoveryModule.inf - -[Rule.Common.SEC] - FILE SEC = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - } - -!include TestFdfInclude.fdf.inc - -# End of FDF diff --git a/test/testInfParsing.inf b/test/testInfParsing.inf deleted file mode 100644 index ba2c3e5..0000000 --- a/test/testInfParsing.inf +++ /dev/null @@ -1,48 +0,0 @@ -## Corner-case INF file for parser tests. - -[Defines] - INF_VERSION = 0x00010017 - BASE_NAME = TestModule - MODULE_TYPE = DXE_DRIVER - ENTRY_POINT = TestEntryPoint - LIBRARY_CLASS = TestLib - CONSTRUCTOR = TestConstructor - DESTRUCTOR = TestDestructor - DEFINE MY_FLAG = TRUE - -[Sources] - TestModule.c - TestModule.h - Subfolder/Helper.c - -[Sources.X64] - X64/Arch.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - BaseLib - DebugLib - UefiBootServicesTableLib - -[Protocols] - gEfiSimpleTextOutProtocolGuid - gEfiDevicePathProtocolGuid - -[Ppis] - gEfiPeiMemoryDiscoveredPpiGuid - -[Guids] - gEfiGlobalVariableGuid - gEfiHobListGuid - -[FixedPcd] - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask - -[Depex] - gEfiVariableArchProtocolGuid AND - gEfiVariableWriteArchProtocolGuid - -# End of INF diff --git a/test/testVfrParsing.vfr b/test/testVfrParsing.vfr deleted file mode 100644 index 11ee5e8..0000000 --- a/test/testVfrParsing.vfr +++ /dev/null @@ -1,78 +0,0 @@ -// Corner-case VFR file for parser tests. - -#include "TestVfrStrDefs.h" - -formset - guid = TEST_FORMSET_GUID, - title = STRING_TOKEN(STR_FORM_SET_TITLE), - help = STRING_TOKEN(STR_FORM_SET_HELP), - - form formid = 1, - title = STRING_TOKEN(STR_FORM1_TITLE); - - oneof - varid = TestData.Option1, - prompt = STRING_TOKEN(STR_OPTION1_PROMPT), - help = STRING_TOKEN(STR_OPTION1_HELP), - option text = STRING_TOKEN(STR_DISABLED), value = 0, flags = DEFAULT; - option text = STRING_TOKEN(STR_ENABLED), value = 1, flags = 0; - endoneof; - - checkbox - varid = TestData.Flag1, - prompt = STRING_TOKEN(STR_FLAG1_PROMPT), - help = STRING_TOKEN(STR_FLAG1_HELP), - flags = CHECKBOX_DEFAULT, - endcheckbox; - - numeric - varid = TestData.Value1, - prompt = STRING_TOKEN(STR_VALUE1_PROMPT), - help = STRING_TOKEN(STR_VALUE1_HELP), - minimum = 0, - maximum = 255, - step = 1, - default = 100, - endnumeric; - - string - varid = TestData.Name1, - prompt = STRING_TOKEN(STR_NAME1_PROMPT), - help = STRING_TOKEN(STR_NAME1_HELP), - minsize = 0, - maxsize = 64, - endstring; - - password - varid = TestData.Pass1, - prompt = STRING_TOKEN(STR_PASS1_PROMPT), - help = STRING_TOKEN(STR_PASS1_HELP), - minsize = 6, - maxsize = 20, - endpassword; - - goto 2, - prompt = STRING_TOKEN(STR_GOTO_FORM2), - help = STRING_TOKEN(STR_GOTO_FORM2_HELP); - - endform; - - form formid = 2, - title = STRING_TOKEN(STR_FORM2_TITLE); - - oneof - varid = TestData.Option2, - prompt = STRING_TOKEN(STR_OPTION2_PROMPT), - help = STRING_TOKEN(STR_OPTION2_HELP), - option text = STRING_TOKEN(STR_LOW), value = 0, flags = DEFAULT; - option text = STRING_TOKEN(STR_MEDIUM), value = 1, flags = 0; - option text = STRING_TOKEN(STR_HIGH), value = 2, flags = 0; - endoneof; - - goto 1, - prompt = STRING_TOKEN(STR_GOTO_FORM1), - help = STRING_TOKEN(STR_GOTO_FORM1_HELP); - - endform; - -endformset; diff --git a/theme/css/codicon.min.css b/theme/css/codicon.min.css new file mode 100755 index 0000000..9f977f6 --- /dev/null +++ b/theme/css/codicon.min.css @@ -0,0 +1,8 @@ +/** + * Minified by jsDelivr using clean-css v5.3.1. + * Original file: /npm/vscode-codicons@0.0.17/dist/codicon.css + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +@font-face{font-family:codicon;src:url("codicon.ttf?54702f639320b60466e6f56678165405") format("truetype")}.codicon[class*=codicon-]{font:normal normal normal 16px/1 codicon;display:inline-block;text-decoration:none;text-rendering:auto;text-align:center;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;user-select:none;-webkit-user-select:none;-ms-user-select:none}.codicon-add:before{content:"\ea60"}.codicon-plus:before{content:"\ea60"}.codicon-gist-new:before{content:"\ea60"}.codicon-repo-create:before{content:"\ea60"}.codicon-lightbulb:before{content:"\ea61"}.codicon-light-bulb:before{content:"\ea61"}.codicon-repo:before{content:"\ea62"}.codicon-repo-delete:before{content:"\ea62"}.codicon-gist-fork:before{content:"\ea63"}.codicon-repo-forked:before{content:"\ea63"}.codicon-git-pull-request:before{content:"\ea64"}.codicon-git-pull-request-abandoned:before{content:"\ea64"}.codicon-record-keys:before{content:"\ea65"}.codicon-keyboard:before{content:"\ea65"}.codicon-tag:before{content:"\ea66"}.codicon-tag-add:before{content:"\ea66"}.codicon-tag-remove:before{content:"\ea66"}.codicon-person:before{content:"\ea67"}.codicon-person-follow:before{content:"\ea67"}.codicon-person-outline:before{content:"\ea67"}.codicon-person-filled:before{content:"\ea67"}.codicon-git-branch:before{content:"\ea68"}.codicon-git-branch-create:before{content:"\ea68"}.codicon-git-branch-delete:before{content:"\ea68"}.codicon-source-control:before{content:"\ea68"}.codicon-mirror:before{content:"\ea69"}.codicon-mirror-public:before{content:"\ea69"}.codicon-star:before{content:"\ea6a"}.codicon-star-add:before{content:"\ea6a"}.codicon-star-delete:before{content:"\ea6a"}.codicon-star-empty:before{content:"\ea6a"}.codicon-comment:before{content:"\ea6b"}.codicon-comment-add:before{content:"\ea6b"}.codicon-alert:before{content:"\ea6c"}.codicon-warning:before{content:"\ea6c"}.codicon-search:before{content:"\ea6d"}.codicon-search-save:before{content:"\ea6d"}.codicon-log-out:before{content:"\ea6e"}.codicon-sign-out:before{content:"\ea6e"}.codicon-log-in:before{content:"\ea6f"}.codicon-sign-in:before{content:"\ea6f"}.codicon-eye:before{content:"\ea70"}.codicon-eye-unwatch:before{content:"\ea70"}.codicon-eye-watch:before{content:"\ea70"}.codicon-circle-filled:before{content:"\ea71"}.codicon-primitive-dot:before{content:"\ea71"}.codicon-close-dirty:before{content:"\ea71"}.codicon-debug-breakpoint:before{content:"\ea71"}.codicon-debug-breakpoint-disabled:before{content:"\ea71"}.codicon-debug-hint:before{content:"\ea71"}.codicon-primitive-square:before{content:"\ea72"}.codicon-edit:before{content:"\ea73"}.codicon-pencil:before{content:"\ea73"}.codicon-info:before{content:"\ea74"}.codicon-issue-opened:before{content:"\ea74"}.codicon-gist-private:before{content:"\ea75"}.codicon-git-fork-private:before{content:"\ea75"}.codicon-lock:before{content:"\ea75"}.codicon-mirror-private:before{content:"\ea75"}.codicon-close:before{content:"\ea76"}.codicon-remove-close:before{content:"\ea76"}.codicon-x:before{content:"\ea76"}.codicon-repo-sync:before{content:"\ea77"}.codicon-sync:before{content:"\ea77"}.codicon-clone:before{content:"\ea78"}.codicon-desktop-download:before{content:"\ea78"}.codicon-beaker:before{content:"\ea79"}.codicon-microscope:before{content:"\ea79"}.codicon-vm:before{content:"\ea7a"}.codicon-device-desktop:before{content:"\ea7a"}.codicon-file:before{content:"\ea7b"}.codicon-file-text:before{content:"\ea7b"}.codicon-more:before{content:"\ea7c"}.codicon-ellipsis:before{content:"\ea7c"}.codicon-kebab-horizontal:before{content:"\ea7c"}.codicon-mail-reply:before{content:"\ea7d"}.codicon-reply:before{content:"\ea7d"}.codicon-organization:before{content:"\ea7e"}.codicon-organization-filled:before{content:"\ea7e"}.codicon-organization-outline:before{content:"\ea7e"}.codicon-new-file:before{content:"\ea7f"}.codicon-file-add:before{content:"\ea7f"}.codicon-new-folder:before{content:"\ea80"}.codicon-file-directory-create:before{content:"\ea80"}.codicon-trash:before{content:"\ea81"}.codicon-trashcan:before{content:"\ea81"}.codicon-history:before{content:"\ea82"}.codicon-clock:before{content:"\ea82"}.codicon-folder:before{content:"\ea83"}.codicon-file-directory:before{content:"\ea83"}.codicon-symbol-folder:before{content:"\ea83"}.codicon-logo-github:before{content:"\ea84"}.codicon-mark-github:before{content:"\ea84"}.codicon-github:before{content:"\ea84"}.codicon-terminal:before{content:"\ea85"}.codicon-console:before{content:"\ea85"}.codicon-repl:before{content:"\ea85"}.codicon-zap:before{content:"\ea86"}.codicon-symbol-event:before{content:"\ea86"}.codicon-error:before{content:"\ea87"}.codicon-stop:before{content:"\ea87"}.codicon-variable:before{content:"\ea88"}.codicon-symbol-variable:before{content:"\ea88"}.codicon-array:before{content:"\ea8a"}.codicon-symbol-array:before{content:"\ea8a"}.codicon-symbol-module:before{content:"\ea8b"}.codicon-symbol-package:before{content:"\ea8b"}.codicon-symbol-namespace:before{content:"\ea8b"}.codicon-symbol-object:before{content:"\ea8b"}.codicon-symbol-method:before{content:"\ea8c"}.codicon-symbol-function:before{content:"\ea8c"}.codicon-symbol-constructor:before{content:"\ea8c"}.codicon-symbol-boolean:before{content:"\ea8f"}.codicon-symbol-null:before{content:"\ea8f"}.codicon-symbol-numeric:before{content:"\ea90"}.codicon-symbol-number:before{content:"\ea90"}.codicon-symbol-structure:before{content:"\ea91"}.codicon-symbol-struct:before{content:"\ea91"}.codicon-symbol-parameter:before{content:"\ea92"}.codicon-symbol-type-parameter:before{content:"\ea92"}.codicon-symbol-key:before{content:"\ea93"}.codicon-symbol-text:before{content:"\ea93"}.codicon-symbol-reference:before{content:"\ea94"}.codicon-go-to-file:before{content:"\ea94"}.codicon-symbol-enum:before{content:"\ea95"}.codicon-symbol-value:before{content:"\ea95"}.codicon-symbol-ruler:before{content:"\ea96"}.codicon-symbol-unit:before{content:"\ea96"}.codicon-activate-breakpoints:before{content:"\ea97"}.codicon-archive:before{content:"\ea98"}.codicon-arrow-both:before{content:"\ea99"}.codicon-arrow-down:before{content:"\ea9a"}.codicon-arrow-left:before{content:"\ea9b"}.codicon-arrow-right:before{content:"\ea9c"}.codicon-arrow-small-down:before{content:"\ea9d"}.codicon-arrow-small-left:before{content:"\ea9e"}.codicon-arrow-small-right:before{content:"\ea9f"}.codicon-arrow-small-up:before{content:"\eaa0"}.codicon-arrow-up:before{content:"\eaa1"}.codicon-bell:before{content:"\eaa2"}.codicon-bold:before{content:"\eaa3"}.codicon-book:before{content:"\eaa4"}.codicon-bookmark:before{content:"\eaa5"}.codicon-debug-breakpoint-conditional-unverified:before{content:"\eaa6"}.codicon-debug-breakpoint-conditional:before{content:"\eaa7"}.codicon-debug-breakpoint-conditional-disabled:before{content:"\eaa7"}.codicon-debug-breakpoint-data-unverified:before{content:"\eaa8"}.codicon-debug-breakpoint-data:before{content:"\eaa9"}.codicon-debug-breakpoint-data-disabled:before{content:"\eaa9"}.codicon-debug-breakpoint-log-unverified:before{content:"\eaaa"}.codicon-debug-breakpoint-log:before{content:"\eaab"}.codicon-debug-breakpoint-log-disabled:before{content:"\eaab"}.codicon-briefcase:before{content:"\eaac"}.codicon-broadcast:before{content:"\eaad"}.codicon-browser:before{content:"\eaae"}.codicon-bug:before{content:"\eaaf"}.codicon-calendar:before{content:"\eab0"}.codicon-case-sensitive:before{content:"\eab1"}.codicon-check:before{content:"\eab2"}.codicon-checklist:before{content:"\eab3"}.codicon-chevron-down:before{content:"\eab4"}.codicon-chevron-left:before{content:"\eab5"}.codicon-chevron-right:before{content:"\eab6"}.codicon-chevron-up:before{content:"\eab7"}.codicon-chrome-close:before{content:"\eab8"}.codicon-chrome-maximize:before{content:"\eab9"}.codicon-chrome-minimize:before{content:"\eaba"}.codicon-chrome-restore:before{content:"\eabb"}.codicon-circle-outline:before{content:"\eabc"}.codicon-debug-breakpoint-unverified:before{content:"\eabc"}.codicon-circle-slash:before{content:"\eabd"}.codicon-circuit-board:before{content:"\eabe"}.codicon-clear-all:before{content:"\eabf"}.codicon-clippy:before{content:"\eac0"}.codicon-close-all:before{content:"\eac1"}.codicon-cloud-download:before{content:"\eac2"}.codicon-cloud-upload:before{content:"\eac3"}.codicon-code:before{content:"\eac4"}.codicon-collapse-all:before{content:"\eac5"}.codicon-color-mode:before{content:"\eac6"}.codicon-comment-discussion:before{content:"\eac7"}.codicon-credit-card:before{content:"\eac9"}.codicon-dash:before{content:"\eacc"}.codicon-dashboard:before{content:"\eacd"}.codicon-database:before{content:"\eace"}.codicon-debug-continue:before{content:"\eacf"}.codicon-debug-disconnect:before{content:"\ead0"}.codicon-debug-pause:before{content:"\ead1"}.codicon-debug-restart:before{content:"\ead2"}.codicon-debug-start:before{content:"\ead3"}.codicon-debug-step-into:before{content:"\ead4"}.codicon-debug-step-out:before{content:"\ead5"}.codicon-debug-step-over:before{content:"\ead6"}.codicon-debug-stop:before{content:"\ead7"}.codicon-debug:before{content:"\ead8"}.codicon-device-camera-video:before{content:"\ead9"}.codicon-device-camera:before{content:"\eada"}.codicon-device-mobile:before{content:"\eadb"}.codicon-diff-added:before{content:"\eadc"}.codicon-diff-ignored:before{content:"\eadd"}.codicon-diff-modified:before{content:"\eade"}.codicon-diff-removed:before{content:"\eadf"}.codicon-diff-renamed:before{content:"\eae0"}.codicon-diff:before{content:"\eae1"}.codicon-discard:before{content:"\eae2"}.codicon-editor-layout:before{content:"\eae3"}.codicon-empty-window:before{content:"\eae4"}.codicon-exclude:before{content:"\eae5"}.codicon-extensions:before{content:"\eae6"}.codicon-eye-closed:before{content:"\eae7"}.codicon-file-binary:before{content:"\eae8"}.codicon-file-code:before{content:"\eae9"}.codicon-file-media:before{content:"\eaea"}.codicon-file-pdf:before{content:"\eaeb"}.codicon-file-submodule:before{content:"\eaec"}.codicon-file-symlink-directory:before{content:"\eaed"}.codicon-file-symlink-file:before{content:"\eaee"}.codicon-file-zip:before{content:"\eaef"}.codicon-files:before{content:"\eaf0"}.codicon-filter:before{content:"\eaf1"}.codicon-flame:before{content:"\eaf2"}.codicon-fold-down:before{content:"\eaf3"}.codicon-fold-up:before{content:"\eaf4"}.codicon-fold:before{content:"\eaf5"}.codicon-folder-active:before{content:"\eaf6"}.codicon-folder-opened:before{content:"\eaf7"}.codicon-gear:before{content:"\eaf8"}.codicon-gift:before{content:"\eaf9"}.codicon-gist-secret:before{content:"\eafa"}.codicon-gist:before{content:"\eafb"}.codicon-git-commit:before{content:"\eafc"}.codicon-git-compare:before{content:"\eafd"}.codicon-compare-changes:before{content:"\eafd"}.codicon-git-merge:before{content:"\eafe"}.codicon-github-action:before{content:"\eaff"}.codicon-github-alt:before{content:"\eb00"}.codicon-globe:before{content:"\eb01"}.codicon-grabber:before{content:"\eb02"}.codicon-graph:before{content:"\eb03"}.codicon-gripper:before{content:"\eb04"}.codicon-heart:before{content:"\eb05"}.codicon-home:before{content:"\eb06"}.codicon-horizontal-rule:before{content:"\eb07"}.codicon-hubot:before{content:"\eb08"}.codicon-inbox:before{content:"\eb09"}.codicon-issue-closed:before{content:"\eb0a"}.codicon-issue-reopened:before{content:"\eb0b"}.codicon-issues:before{content:"\eb0c"}.codicon-italic:before{content:"\eb0d"}.codicon-jersey:before{content:"\eb0e"}.codicon-json:before{content:"\eb0f"}.codicon-kebab-vertical:before{content:"\eb10"}.codicon-key:before{content:"\eb11"}.codicon-law:before{content:"\eb12"}.codicon-lightbulb-autofix:before{content:"\eb13"}.codicon-link-external:before{content:"\eb14"}.codicon-link:before{content:"\eb15"}.codicon-list-ordered:before{content:"\eb16"}.codicon-list-unordered:before{content:"\eb17"}.codicon-live-share:before{content:"\eb18"}.codicon-loading:before{content:"\eb19"}.codicon-location:before{content:"\eb1a"}.codicon-mail-read:before{content:"\eb1b"}.codicon-mail:before{content:"\eb1c"}.codicon-markdown:before{content:"\eb1d"}.codicon-megaphone:before{content:"\eb1e"}.codicon-mention:before{content:"\eb1f"}.codicon-milestone:before{content:"\eb20"}.codicon-mortar-board:before{content:"\eb21"}.codicon-move:before{content:"\eb22"}.codicon-multiple-windows:before{content:"\eb23"}.codicon-mute:before{content:"\eb24"}.codicon-no-newline:before{content:"\eb25"}.codicon-note:before{content:"\eb26"}.codicon-octoface:before{content:"\eb27"}.codicon-open-preview:before{content:"\eb28"}.codicon-package:before{content:"\eb29"}.codicon-paintcan:before{content:"\eb2a"}.codicon-pin:before{content:"\eb2b"}.codicon-play:before{content:"\eb2c"}.codicon-run:before{content:"\eb2c"}.codicon-plug:before{content:"\eb2d"}.codicon-preserve-case:before{content:"\eb2e"}.codicon-preview:before{content:"\eb2f"}.codicon-project:before{content:"\eb30"}.codicon-pulse:before{content:"\eb31"}.codicon-question:before{content:"\eb32"}.codicon-quote:before{content:"\eb33"}.codicon-radio-tower:before{content:"\eb34"}.codicon-reactions:before{content:"\eb35"}.codicon-references:before{content:"\eb36"}.codicon-refresh:before{content:"\eb37"}.codicon-regex:before{content:"\eb38"}.codicon-remote-explorer:before{content:"\eb39"}.codicon-remote:before{content:"\eb3a"}.codicon-remove:before{content:"\eb3b"}.codicon-replace-all:before{content:"\eb3c"}.codicon-replace:before{content:"\eb3d"}.codicon-repo-clone:before{content:"\eb3e"}.codicon-repo-force-push:before{content:"\eb3f"}.codicon-repo-pull:before{content:"\eb40"}.codicon-repo-push:before{content:"\eb41"}.codicon-report:before{content:"\eb42"}.codicon-request-changes:before{content:"\eb43"}.codicon-rocket:before{content:"\eb44"}.codicon-root-folder-opened:before{content:"\eb45"}.codicon-root-folder:before{content:"\eb46"}.codicon-rss:before{content:"\eb47"}.codicon-ruby:before{content:"\eb48"}.codicon-save-all:before{content:"\eb49"}.codicon-save-as:before{content:"\eb4a"}.codicon-save:before{content:"\eb4b"}.codicon-screen-full:before{content:"\eb4c"}.codicon-screen-normal:before{content:"\eb4d"}.codicon-search-stop:before{content:"\eb4e"}.codicon-server:before{content:"\eb50"}.codicon-settings-gear:before{content:"\eb51"}.codicon-settings:before{content:"\eb52"}.codicon-shield:before{content:"\eb53"}.codicon-smiley:before{content:"\eb54"}.codicon-sort-precedence:before{content:"\eb55"}.codicon-split-horizontal:before{content:"\eb56"}.codicon-split-vertical:before{content:"\eb57"}.codicon-squirrel:before{content:"\eb58"}.codicon-star-full:before{content:"\eb59"}.codicon-star-half:before{content:"\eb5a"}.codicon-symbol-class:before{content:"\eb5b"}.codicon-symbol-color:before{content:"\eb5c"}.codicon-symbol-constant:before{content:"\eb5d"}.codicon-symbol-enum-member:before{content:"\eb5e"}.codicon-symbol-field:before{content:"\eb5f"}.codicon-symbol-file:before{content:"\eb60"}.codicon-symbol-interface:before{content:"\eb61"}.codicon-symbol-keyword:before{content:"\eb62"}.codicon-symbol-misc:before{content:"\eb63"}.codicon-symbol-operator:before{content:"\eb64"}.codicon-symbol-property:before{content:"\eb65"}.codicon-wrench:before{content:"\eb65"}.codicon-wrench-subaction:before{content:"\eb65"}.codicon-symbol-snippet:before{content:"\eb66"}.codicon-tasklist:before{content:"\eb67"}.codicon-telescope:before{content:"\eb68"}.codicon-text-size:before{content:"\eb69"}.codicon-three-bars:before{content:"\eb6a"}.codicon-thumbsdown:before{content:"\eb6b"}.codicon-thumbsup:before{content:"\eb6c"}.codicon-tools:before{content:"\eb6d"}.codicon-triangle-down:before{content:"\eb6e"}.codicon-triangle-left:before{content:"\eb6f"}.codicon-triangle-right:before{content:"\eb70"}.codicon-triangle-up:before{content:"\eb71"}.codicon-twitter:before{content:"\eb72"}.codicon-unfold:before{content:"\eb73"}.codicon-unlock:before{content:"\eb74"}.codicon-unmute:before{content:"\eb75"}.codicon-unverified:before{content:"\eb76"}.codicon-verified:before{content:"\eb77"}.codicon-versions:before{content:"\eb78"}.codicon-vm-active:before{content:"\eb79"}.codicon-vm-outline:before{content:"\eb7a"}.codicon-vm-running:before{content:"\eb7b"}.codicon-watch:before{content:"\eb7c"}.codicon-whitespace:before{content:"\eb7d"}.codicon-whole-word:before{content:"\eb7e"}.codicon-window:before{content:"\eb7f"}.codicon-word-wrap:before{content:"\eb80"}.codicon-zoom-in:before{content:"\eb81"}.codicon-zoom-out:before{content:"\eb82"}.codicon-list-filter:before{content:"\eb83"}.codicon-list-flat:before{content:"\eb84"}.codicon-list-selection:before{content:"\eb85"}.codicon-selection:before{content:"\eb85"}.codicon-list-tree:before{content:"\eb86"}.codicon-debug-breakpoint-function-unverified:before{content:"\eb87"}.codicon-debug-breakpoint-function:before{content:"\eb88"}.codicon-debug-breakpoint-function-disabled:before{content:"\eb88"}.codicon-debug-stackframe-active:before{content:"\eb89"}.codicon-debug-stackframe-dot:before{content:"\eb8a"}.codicon-debug-stackframe:before{content:"\eb8b"}.codicon-debug-stackframe-focused:before{content:"\eb8b"}.codicon-debug-breakpoint-unsupported:before{content:"\eb8c"}.codicon-symbol-string:before{content:"\eb8d"}.codicon-debug-reverse-continue:before{content:"\eb8e"}.codicon-debug-step-back:before{content:"\eb8f"}.codicon-debug-restart-frame:before{content:"\eb90"}.codicon-debug-alt:before{content:"\eb91"}.codicon-call-incoming:before{content:"\eb92"}.codicon-call-outgoing:before{content:"\eb93"}.codicon-menu:before{content:"\eb94"}.codicon-expand-all:before{content:"\eb95"}.codicon-feedback:before{content:"\eb96"}.codicon-group-by-ref-type:before{content:"\eb97"}.codicon-ungroup-by-ref-type:before{content:"\eb98"}.codicon-account:before{content:"\eb99"}.codicon-bell-dot:before{content:"\eb9a"}.codicon-debug-console:before{content:"\eb9b"}.codicon-library:before{content:"\eb9c"}.codicon-output:before{content:"\eb9d"}.codicon-run-all:before{content:"\eb9e"}.codicon-sync-ignored:before{content:"\eb9f"}.codicon-pinned:before{content:"\eba0"}.codicon-github-inverted:before{content:"\eba1"}.codicon-server-process:before{content:"\eba2"}.codicon-server-environment:before{content:"\eba3"}.codicon-pass:before{content:"\eba4"}.codicon-stop-circle:before{content:"\eba5"}.codicon-play-circle:before{content:"\eba6"}.codicon-record:before{content:"\eba7"}.codicon-debug-alt-small:before{content:"\eba8"}.codicon-vm-connect:before{content:"\eba9"}.codicon-cloud:before{content:"\ebaa"}.codicon-merge:before{content:"\ebab"}.codicon-export:before{content:"\ebac"}.codicon-graph-left:before{content:"\ebad"}.codicon-magnet:before{content:"\ebae"}.codicon-notebook:before{content:"\ebaf"}.codicon-redo:before{content:"\ebb0"}.codicon-check-all:before{content:"\ebb1"}.codicon-pinned-dirty:before{content:"\ebb2"}.codicon-pass-filled:before{content:"\ebb3"}.codicon-circle-large-filled:before{content:"\ebb4"}.codicon-circle-large-outline:before{content:"\ebb5"}.codicon-combine:before{content:"\ebb6"}.codicon-gather:before{content:"\ebb6"}.codicon-table:before{content:"\ebb7"}.codicon-variable-group:before{content:"\ebb8"}.codicon-type-hierarchy:before{content:"\ebb9"}.codicon-type-hierarchy-sub:before{content:"\ebba"}.codicon-type-hierarchy-super:before{content:"\ebbb"}.codicon-git-pull-request-create:before{content:"\ebbc"}.codicon-run-above:before{content:"\ebbd"}.codicon-run-below:before{content:"\ebbe"}.codicon-notebook-template:before{content:"\ebbf"}.codicon-debug-rerun:before{content:"\ebc0"}.codicon-workspace-trusted:before{content:"\ebc1"}.codicon-workspace-untrusted:before{content:"\ebc2"}.codicon-workspace-unknown:before{content:"\ebc3"}.codicon-terminal-cmd:before{content:"\ebc4"}.codicon-terminal-debian:before{content:"\ebc5"}.codicon-terminal-linux:before{content:"\ebc6"}.codicon-terminal-powershell:before{content:"\ebc7"}.codicon-terminal-tmux:before{content:"\ebc8"}.codicon-terminal-ubuntu:before{content:"\ebc9"}.codicon-terminal-bash:before{content:"\ebca"}.codicon-arrow-swap:before{content:"\ebcb"}.codicon-copy:before{content:"\ebcc"}.codicon-person-add:before{content:"\ebcd"}.codicon-filter-filled:before{content:"\ebce"}.codicon-wand:before{content:"\ebcf"}.codicon-debug-line-by-line:before{content:"\ebd0"} +/*# sourceMappingURL=/sm/47c7ce03f4cac9715a318ba6ea5c13243805f44c191b161889f343f193aee1e3.map */ \ No newline at end of file diff --git a/theme/css/codicon.ttf b/theme/css/codicon.ttf new file mode 100755 index 0000000..807c949 Binary files /dev/null and b/theme/css/codicon.ttf differ diff --git a/theme/css/extra.css b/theme/css/extra.css new file mode 100755 index 0000000..0842339 --- /dev/null +++ b/theme/css/extra.css @@ -0,0 +1,33 @@ +.clipboard { + position: relative; + display: block; + float: right; + right: 29px; + line-height: 0px; + width: 0px; + top: 10px; + font-size: x-small; + cursor: pointer; + color: rgb(0,0,0,0.5); +} + +.header-link span.btn-clipboard-link { + display: none; +} + +.header-link:hover span.btn-clipboard-link { + display: inline; +} + +.clipboard:hover { + color: var(--md-accent-fg-color); + transition: color 125ms; +} + +.btn-clipboard-link{ + margin-left: 5px; + cursor: pointer; + color: rgb(0,0,0,0.5); + +} + diff --git a/theme/js/clipboard.min.js b/theme/js/clipboard.min.js new file mode 100755 index 0000000..9f97edb --- /dev/null +++ b/theme/js/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=10&&s(a.width)/e.offsetWidth||1,p=e.offsetHeight>0&&s(a.height)/e.offsetHeight||1);var u=(n(e)?t(e):window).visualViewport,l=!c()&&i,d=(a.left+(l&&u?u.offsetLeft:0))/f,h=(a.top+(l&&u?u.offsetTop:0))/p,m=a.width/f,v=a.height/p;return{width:m,height:v,top:h,right:d+m,bottom:h+v,left:d,x:d,y:h}}function u(e){var n=t(e);return{scrollLeft:n.pageXOffset,scrollTop:n.pageYOffset}}function l(e){return e?(e.nodeName||"").toLowerCase():null}function d(e){return((n(e)?e.ownerDocument:e.document)||window.document).documentElement}function h(e){return p(d(e)).left+u(e).scrollLeft}function m(e){return t(e).getComputedStyle(e)}function v(e){var t=m(e),n=t.overflow,r=t.overflowX,o=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+r)}function y(e,n,o){void 0===o&&(o=!1);var i,a,f=r(n),c=r(n)&&function(e){var t=e.getBoundingClientRect(),n=s(t.width)/e.offsetWidth||1,r=s(t.height)/e.offsetHeight||1;return 1!==n||1!==r}(n),m=d(n),y=p(e,c,o),g={scrollLeft:0,scrollTop:0},b={x:0,y:0};return(f||!f&&!o)&&(("body"!==l(n)||v(m))&&(g=(i=n)!==t(i)&&r(i)?{scrollLeft:(a=i).scrollLeft,scrollTop:a.scrollTop}:u(i)),r(n)?((b=p(n,!0)).x+=n.clientLeft,b.y+=n.clientTop):m&&(b.x=h(m))),{x:y.left+g.scrollLeft-b.x,y:y.top+g.scrollTop-b.y,width:y.width,height:y.height}}function g(e){var t=p(e),n=e.offsetWidth,r=e.offsetHeight;return Math.abs(t.width-n)<=1&&(n=t.width),Math.abs(t.height-r)<=1&&(r=t.height),{x:e.offsetLeft,y:e.offsetTop,width:n,height:r}}function b(e){return"html"===l(e)?e:e.assignedSlot||e.parentNode||(o(e)?e.host:null)||d(e)}function x(e){return["html","body","#document"].indexOf(l(e))>=0?e.ownerDocument.body:r(e)&&v(e)?e:x(b(e))}function w(e,n){var r;void 0===n&&(n=[]);var o=x(e),i=o===(null==(r=e.ownerDocument)?void 0:r.body),a=t(o),s=i?[a].concat(a.visualViewport||[],v(o)?o:[]):o,f=n.concat(s);return i?f:f.concat(w(b(s)))}function O(e){return["table","td","th"].indexOf(l(e))>=0}function j(e){return r(e)&&"fixed"!==m(e).position?e.offsetParent:null}function E(e){for(var n=t(e),i=j(e);i&&O(i)&&"static"===m(i).position;)i=j(i);return i&&("html"===l(i)||"body"===l(i)&&"static"===m(i).position)?n:i||function(e){var t=/firefox/i.test(f());if(/Trident/i.test(f())&&r(e)&&"fixed"===m(e).position)return null;var n=b(e);for(o(n)&&(n=n.host);r(n)&&["html","body"].indexOf(l(n))<0;){var i=m(n);if("none"!==i.transform||"none"!==i.perspective||"paint"===i.contain||-1!==["transform","perspective"].indexOf(i.willChange)||t&&"filter"===i.willChange||t&&i.filter&&"none"!==i.filter)return n;n=n.parentNode}return null}(e)||n}var D="top",A="bottom",L="right",P="left",M="auto",k=[D,A,L,P],W="start",B="end",H="viewport",T="popper",R=k.reduce((function(e,t){return e.concat([t+"-"+W,t+"-"+B])}),[]),S=[].concat(k,[M]).reduce((function(e,t){return e.concat([t,t+"-"+W,t+"-"+B])}),[]),V=["beforeRead","read","afterRead","beforeMain","main","afterMain","beforeWrite","write","afterWrite"];function q(e){var t=new Map,n=new Set,r=[];function o(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var r=t.get(e);r&&o(r)}})),r.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||o(e)})),r}function C(e,t){var n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&o(n)){var r=t;do{if(r&&e.isSameNode(r))return!0;r=r.parentNode||r.host}while(r)}return!1}function N(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}function I(e,r,o){return r===H?N(function(e,n){var r=t(e),o=d(e),i=r.visualViewport,a=o.clientWidth,s=o.clientHeight,f=0,p=0;if(i){a=i.width,s=i.height;var u=c();(u||!u&&"fixed"===n)&&(f=i.offsetLeft,p=i.offsetTop)}return{width:a,height:s,x:f+h(e),y:p}}(e,o)):n(r)?function(e,t){var n=p(e,!1,"fixed"===t);return n.top=n.top+e.clientTop,n.left=n.left+e.clientLeft,n.bottom=n.top+e.clientHeight,n.right=n.left+e.clientWidth,n.width=e.clientWidth,n.height=e.clientHeight,n.x=n.left,n.y=n.top,n}(r,o):N(function(e){var t,n=d(e),r=u(e),o=null==(t=e.ownerDocument)?void 0:t.body,a=i(n.scrollWidth,n.clientWidth,o?o.scrollWidth:0,o?o.clientWidth:0),s=i(n.scrollHeight,n.clientHeight,o?o.scrollHeight:0,o?o.clientHeight:0),f=-r.scrollLeft+h(e),c=-r.scrollTop;return"rtl"===m(o||n).direction&&(f+=i(n.clientWidth,o?o.clientWidth:0)-a),{width:a,height:s,x:f,y:c}}(d(e)))}function _(e,t,o,s){var f="clippingParents"===t?function(e){var t=w(b(e)),o=["absolute","fixed"].indexOf(m(e).position)>=0&&r(e)?E(e):e;return n(o)?t.filter((function(e){return n(e)&&C(e,o)&&"body"!==l(e)})):[]}(e):[].concat(t),c=[].concat(f,[o]),p=c[0],u=c.reduce((function(t,n){var r=I(e,n,s);return t.top=i(r.top,t.top),t.right=a(r.right,t.right),t.bottom=a(r.bottom,t.bottom),t.left=i(r.left,t.left),t}),I(e,p,s));return u.width=u.right-u.left,u.height=u.bottom-u.top,u.x=u.left,u.y=u.top,u}function F(e){return e.split("-")[0]}function U(e){return e.split("-")[1]}function z(e){return["top","bottom"].indexOf(e)>=0?"x":"y"}function X(e){var t,n=e.reference,r=e.element,o=e.placement,i=o?F(o):null,a=o?U(o):null,s=n.x+n.width/2-r.width/2,f=n.y+n.height/2-r.height/2;switch(i){case D:t={x:s,y:n.y-r.height};break;case A:t={x:s,y:n.y+n.height};break;case L:t={x:n.x+n.width,y:f};break;case P:t={x:n.x-r.width,y:f};break;default:t={x:n.x,y:n.y}}var c=i?z(i):null;if(null!=c){var p="y"===c?"height":"width";switch(a){case W:t[c]=t[c]-(n[p]/2-r[p]/2);break;case B:t[c]=t[c]+(n[p]/2-r[p]/2)}}return t}function Y(e){return Object.assign({},{top:0,right:0,bottom:0,left:0},e)}function G(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}function J(e,t){void 0===t&&(t={});var r=t,o=r.placement,i=void 0===o?e.placement:o,a=r.strategy,s=void 0===a?e.strategy:a,f=r.boundary,c=void 0===f?"clippingParents":f,u=r.rootBoundary,l=void 0===u?H:u,h=r.elementContext,m=void 0===h?T:h,v=r.altBoundary,y=void 0!==v&&v,g=r.padding,b=void 0===g?0:g,x=Y("number"!=typeof b?b:G(b,k)),w=m===T?"reference":T,O=e.rects.popper,j=e.elements[y?w:m],E=_(n(j)?j:j.contextElement||d(e.elements.popper),c,l,s),P=p(e.elements.reference),M=X({reference:P,element:O,strategy:"absolute",placement:i}),W=N(Object.assign({},O,M)),B=m===T?W:P,R={top:E.top-B.top+x.top,bottom:B.bottom-E.bottom+x.bottom,left:E.left-B.left+x.left,right:B.right-E.right+x.right},S=e.modifiersData.offset;if(m===T&&S){var V=S[i];Object.keys(R).forEach((function(e){var t=[L,A].indexOf(e)>=0?1:-1,n=[D,A].indexOf(e)>=0?"y":"x";R[e]+=V[n]*t}))}return R}var K={placement:"bottom",modifiers:[],strategy:"absolute"};function Q(){for(var e=arguments.length,t=new Array(e),n=0;n=0?-1:1,i="function"==typeof n?n(Object.assign({},t,{placement:e})):n,a=i[0],s=i[1];return a=a||0,s=(s||0)*o,[P,L].indexOf(r)>=0?{x:s,y:a}:{x:a,y:s}}(n,t.rects,i),e}),{}),s=a[t.placement],f=s.x,c=s.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=f,t.modifiersData.popperOffsets.y+=c),t.modifiersData[r]=a}},se={left:"right",right:"left",bottom:"top",top:"bottom"};function fe(e){return e.replace(/left|right|bottom|top/g,(function(e){return se[e]}))}var ce={start:"end",end:"start"};function pe(e){return e.replace(/start|end/g,(function(e){return ce[e]}))}function ue(e,t){void 0===t&&(t={});var n=t,r=n.placement,o=n.boundary,i=n.rootBoundary,a=n.padding,s=n.flipVariations,f=n.allowedAutoPlacements,c=void 0===f?S:f,p=U(r),u=p?s?R:R.filter((function(e){return U(e)===p})):k,l=u.filter((function(e){return c.indexOf(e)>=0}));0===l.length&&(l=u);var d=l.reduce((function(t,n){return t[n]=J(e,{placement:n,boundary:o,rootBoundary:i,padding:a})[F(n)],t}),{});return Object.keys(d).sort((function(e,t){return d[e]-d[t]}))}var le={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name;if(!t.modifiersData[r]._skip){for(var o=n.mainAxis,i=void 0===o||o,a=n.altAxis,s=void 0===a||a,f=n.fallbackPlacements,c=n.padding,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.flipVariations,h=void 0===d||d,m=n.allowedAutoPlacements,v=t.options.placement,y=F(v),g=f||(y===v||!h?[fe(v)]:function(e){if(F(e)===M)return[];var t=fe(e);return[pe(e),t,pe(t)]}(v)),b=[v].concat(g).reduce((function(e,n){return e.concat(F(n)===M?ue(t,{placement:n,boundary:p,rootBoundary:u,padding:c,flipVariations:h,allowedAutoPlacements:m}):n)}),[]),x=t.rects.reference,w=t.rects.popper,O=new Map,j=!0,E=b[0],k=0;k=0,S=R?"width":"height",V=J(t,{placement:B,boundary:p,rootBoundary:u,altBoundary:l,padding:c}),q=R?T?L:P:T?A:D;x[S]>w[S]&&(q=fe(q));var C=fe(q),N=[];if(i&&N.push(V[H]<=0),s&&N.push(V[q]<=0,V[C]<=0),N.every((function(e){return e}))){E=B,j=!1;break}O.set(B,N)}if(j)for(var I=function(e){var t=b.find((function(t){var n=O.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return E=t,"break"},_=h?3:1;_>0;_--){if("break"===I(_))break}t.placement!==E&&(t.modifiersData[r]._skip=!0,t.placement=E,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function de(e,t,n){return i(e,a(t,n))}var he={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,r=e.name,o=n.mainAxis,s=void 0===o||o,f=n.altAxis,c=void 0!==f&&f,p=n.boundary,u=n.rootBoundary,l=n.altBoundary,d=n.padding,h=n.tether,m=void 0===h||h,v=n.tetherOffset,y=void 0===v?0:v,b=J(t,{boundary:p,rootBoundary:u,padding:d,altBoundary:l}),x=F(t.placement),w=U(t.placement),O=!w,j=z(x),M="x"===j?"y":"x",k=t.modifiersData.popperOffsets,B=t.rects.reference,H=t.rects.popper,T="function"==typeof y?y(Object.assign({},t.rects,{placement:t.placement})):y,R="number"==typeof T?{mainAxis:T,altAxis:T}:Object.assign({mainAxis:0,altAxis:0},T),S=t.modifiersData.offset?t.modifiersData.offset[t.placement]:null,V={x:0,y:0};if(k){if(s){var q,C="y"===j?D:P,N="y"===j?A:L,I="y"===j?"height":"width",_=k[j],X=_+b[C],Y=_-b[N],G=m?-H[I]/2:0,K=w===W?B[I]:H[I],Q=w===W?-H[I]:-B[I],Z=t.elements.arrow,$=m&&Z?g(Z):{width:0,height:0},ee=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},te=ee[C],ne=ee[N],re=de(0,B[I],$[I]),oe=O?B[I]/2-G-re-te-R.mainAxis:K-re-te-R.mainAxis,ie=O?-B[I]/2+G+re+ne+R.mainAxis:Q+re+ne+R.mainAxis,ae=t.elements.arrow&&E(t.elements.arrow),se=ae?"y"===j?ae.clientTop||0:ae.clientLeft||0:0,fe=null!=(q=null==S?void 0:S[j])?q:0,ce=_+ie-fe,pe=de(m?a(X,_+oe-fe-se):X,_,m?i(Y,ce):Y);k[j]=pe,V[j]=pe-_}if(c){var ue,le="x"===j?D:P,he="x"===j?A:L,me=k[M],ve="y"===M?"height":"width",ye=me+b[le],ge=me-b[he],be=-1!==[D,P].indexOf(x),xe=null!=(ue=null==S?void 0:S[M])?ue:0,we=be?ye:me-B[ve]-H[ve]-xe+R.altAxis,Oe=be?me+B[ve]+H[ve]-xe-R.altAxis:ge,je=m&&be?function(e,t,n){var r=de(e,t,n);return r>n?n:r}(we,me,Oe):de(m?we:ye,me,m?Oe:ge);k[M]=je,V[M]=je-me}t.modifiersData[r]=V}},requiresIfExists:["offset"]};var me={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,r=e.name,o=e.options,i=n.elements.arrow,a=n.modifiersData.popperOffsets,s=F(n.placement),f=z(s),c=[P,L].indexOf(s)>=0?"height":"width";if(i&&a){var p=function(e,t){return Y("number"!=typeof(e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e)?e:G(e,k))}(o.padding,n),u=g(i),l="y"===f?D:P,d="y"===f?A:L,h=n.rects.reference[c]+n.rects.reference[f]-a[f]-n.rects.popper[c],m=a[f]-n.rects.reference[f],v=E(i),y=v?"y"===f?v.clientHeight||0:v.clientWidth||0:0,b=h/2-m/2,x=p[l],w=y-u[c]-p[d],O=y/2-u[c]/2+b,j=de(x,O,w),M=f;n.modifiersData[r]=((t={})[M]=j,t.centerOffset=j-O,t)}},effect:function(e){var t=e.state,n=e.options.element,r=void 0===n?"[data-popper-arrow]":n;null!=r&&("string"!=typeof r||(r=t.elements.popper.querySelector(r)))&&C(t.elements.popper,r)&&(t.elements.arrow=r)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ve(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function ye(e){return[D,L,A,P].some((function(t){return e[t]>=0}))}var ge={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,r=t.rects.reference,o=t.rects.popper,i=t.modifiersData.preventOverflow,a=J(t,{elementContext:"reference"}),s=J(t,{altBoundary:!0}),f=ve(a,r),c=ve(s,o,i),p=ye(f),u=ye(c);t.modifiersData[n]={referenceClippingOffsets:f,popperEscapeOffsets:c,isReferenceHidden:p,hasPopperEscaped:u},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":p,"data-popper-escaped":u})}},be=Z({defaultModifiers:[ee,te,oe,ie]}),xe=[ee,te,oe,ie,ae,le,he,me,ge],we=Z({defaultModifiers:xe});e.applyStyles=ie,e.arrow=me,e.computeStyles=oe,e.createPopper=we,e.createPopperLite=be,e.defaultModifiers=xe,e.detectOverflow=J,e.eventListeners=ee,e.flip=le,e.hide=ge,e.offset=ae,e.popperGenerator=Z,e.popperOffsets=te,e.preventOverflow=he,Object.defineProperty(e,"__esModule",{value:!0})})); +//# sourceMappingURL=popper.min.js.map diff --git a/theme/js/tippy-bundle.umd.min.js b/theme/js/tippy-bundle.umd.min.js new file mode 100755 index 0000000..2f5b298 --- /dev/null +++ b/theme/js/tippy-bundle.umd.min.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("@popperjs/core")):"function"==typeof define&&define.amd?define(["@popperjs/core"],e):(t=t||self).tippy=e(t.Popper)}(this,(function(t){"use strict";var e="undefined"!=typeof window&&"undefined"!=typeof document,n=!!e&&!!window.msCrypto,r={passive:!0,capture:!0},o=function(){return document.body};function i(t,e,n){if(Array.isArray(t)){var r=t[e];return null==r?Array.isArray(n)?n[e]:n:r}return t}function a(t,e){var n={}.toString.call(t);return 0===n.indexOf("[object")&&n.indexOf(e+"]")>-1}function s(t,e){return"function"==typeof t?t.apply(void 0,e):t}function u(t,e){return 0===e?t:function(r){clearTimeout(n),n=setTimeout((function(){t(r)}),e)};var n}function p(t,e){var n=Object.assign({},t);return e.forEach((function(t){delete n[t]})),n}function c(t){return[].concat(t)}function f(t,e){-1===t.indexOf(e)&&t.push(e)}function l(t){return t.split("-")[0]}function d(t){return[].slice.call(t)}function v(t){return Object.keys(t).reduce((function(e,n){return void 0!==t[n]&&(e[n]=t[n]),e}),{})}function m(){return document.createElement("div")}function g(t){return["Element","Fragment"].some((function(e){return a(t,e)}))}function h(t){return a(t,"MouseEvent")}function b(t){return!(!t||!t._tippy||t._tippy.reference!==t)}function y(t){return g(t)?[t]:function(t){return a(t,"NodeList")}(t)?d(t):Array.isArray(t)?t:d(document.querySelectorAll(t))}function w(t,e){t.forEach((function(t){t&&(t.style.transitionDuration=e+"ms")}))}function x(t,e){t.forEach((function(t){t&&t.setAttribute("data-state",e)}))}function E(t){var e,n=c(t)[0];return null!=n&&null!=(e=n.ownerDocument)&&e.body?n.ownerDocument:document}function O(t,e,n){var r=e+"EventListener";["transitionend","webkitTransitionEnd"].forEach((function(e){t[r](e,n)}))}function C(t,e){for(var n=e;n;){var r;if(t.contains(n))return!0;n=null==n.getRootNode||null==(r=n.getRootNode())?void 0:r.host}return!1}var T={isTouch:!1},A=0;function L(){T.isTouch||(T.isTouch=!0,window.performance&&document.addEventListener("mousemove",D))}function D(){var t=performance.now();t-A<20&&(T.isTouch=!1,document.removeEventListener("mousemove",D)),A=t}function k(){var t=document.activeElement;if(b(t)){var e=t._tippy;t.blur&&!e.state.isVisible&&t.blur()}}var R=Object.assign({appendTo:o,aria:{content:"auto",expanded:"auto"},delay:0,duration:[300,250],getReferenceClientRect:null,hideOnClick:!0,ignoreAttributes:!1,interactive:!1,interactiveBorder:2,interactiveDebounce:0,moveTransition:"",offset:[0,10],onAfterUpdate:function(){},onBeforeUpdate:function(){},onCreate:function(){},onDestroy:function(){},onHidden:function(){},onHide:function(){},onMount:function(){},onShow:function(){},onShown:function(){},onTrigger:function(){},onUntrigger:function(){},onClickOutside:function(){},placement:"top",plugins:[],popperOptions:{},render:null,showOnCreate:!1,touch:!0,trigger:"mouseenter focus",triggerTarget:null},{animateFill:!1,followCursor:!1,inlinePositioning:!1,sticky:!1},{allowHTML:!1,animation:"fade",arrow:!0,content:"",inertia:!1,maxWidth:350,role:"tooltip",theme:"",zIndex:9999}),P=Object.keys(R);function j(t){var e=(t.plugins||[]).reduce((function(e,n){var r,o=n.name,i=n.defaultValue;o&&(e[o]=void 0!==t[o]?t[o]:null!=(r=R[o])?r:i);return e}),{});return Object.assign({},t,e)}function M(t,e){var n=Object.assign({},e,{content:s(e.content,[t])},e.ignoreAttributes?{}:function(t,e){return(e?Object.keys(j(Object.assign({},R,{plugins:e}))):P).reduce((function(e,n){var r=(t.getAttribute("data-tippy-"+n)||"").trim();if(!r)return e;if("content"===n)e[n]=r;else try{e[n]=JSON.parse(r)}catch(t){e[n]=r}return e}),{})}(t,e.plugins));return n.aria=Object.assign({},R.aria,n.aria),n.aria={expanded:"auto"===n.aria.expanded?e.interactive:n.aria.expanded,content:"auto"===n.aria.content?e.interactive?null:"describedby":n.aria.content},n}function V(t,e){t.innerHTML=e}function I(t){var e=m();return!0===t?e.className="tippy-arrow":(e.className="tippy-svg-arrow",g(t)?e.appendChild(t):V(e,t)),e}function S(t,e){g(e.content)?(V(t,""),t.appendChild(e.content)):"function"!=typeof e.content&&(e.allowHTML?V(t,e.content):t.textContent=e.content)}function B(t){var e=t.firstElementChild,n=d(e.children);return{box:e,content:n.find((function(t){return t.classList.contains("tippy-content")})),arrow:n.find((function(t){return t.classList.contains("tippy-arrow")||t.classList.contains("tippy-svg-arrow")})),backdrop:n.find((function(t){return t.classList.contains("tippy-backdrop")}))}}function N(t){var e=m(),n=m();n.className="tippy-box",n.setAttribute("data-state","hidden"),n.setAttribute("tabindex","-1");var r=m();function o(n,r){var o=B(e),i=o.box,a=o.content,s=o.arrow;r.theme?i.setAttribute("data-theme",r.theme):i.removeAttribute("data-theme"),"string"==typeof r.animation?i.setAttribute("data-animation",r.animation):i.removeAttribute("data-animation"),r.inertia?i.setAttribute("data-inertia",""):i.removeAttribute("data-inertia"),i.style.maxWidth="number"==typeof r.maxWidth?r.maxWidth+"px":r.maxWidth,r.role?i.setAttribute("role",r.role):i.removeAttribute("role"),n.content===r.content&&n.allowHTML===r.allowHTML||S(a,t.props),r.arrow?s?n.arrow!==r.arrow&&(i.removeChild(s),i.appendChild(I(r.arrow))):i.appendChild(I(r.arrow)):s&&i.removeChild(s)}return r.className="tippy-content",r.setAttribute("data-state","hidden"),S(r,t.props),e.appendChild(n),n.appendChild(r),o(t.props,t.props),{popper:e,onUpdate:o}}N.$$tippy=!0;var H=1,U=[],_=[];function z(e,a){var p,g,b,y,A,L,D,k,P=M(e,Object.assign({},R,j(v(a)))),V=!1,I=!1,S=!1,N=!1,z=[],F=u(wt,P.interactiveDebounce),W=H++,X=(k=P.plugins).filter((function(t,e){return k.indexOf(t)===e})),Y={id:W,reference:e,popper:m(),popperInstance:null,props:P,state:{isEnabled:!0,isVisible:!1,isDestroyed:!1,isMounted:!1,isShown:!1},plugins:X,clearDelayTimeouts:function(){clearTimeout(p),clearTimeout(g),cancelAnimationFrame(b)},setProps:function(t){if(Y.state.isDestroyed)return;at("onBeforeUpdate",[Y,t]),bt();var n=Y.props,r=M(e,Object.assign({},n,v(t),{ignoreAttributes:!0}));Y.props=r,ht(),n.interactiveDebounce!==r.interactiveDebounce&&(pt(),F=u(wt,r.interactiveDebounce));n.triggerTarget&&!r.triggerTarget?c(n.triggerTarget).forEach((function(t){t.removeAttribute("aria-expanded")})):r.triggerTarget&&e.removeAttribute("aria-expanded");ut(),it(),J&&J(n,r);Y.popperInstance&&(Ct(),At().forEach((function(t){requestAnimationFrame(t._tippy.popperInstance.forceUpdate)})));at("onAfterUpdate",[Y,t])},setContent:function(t){Y.setProps({content:t})},show:function(){var t=Y.state.isVisible,e=Y.state.isDestroyed,n=!Y.state.isEnabled,r=T.isTouch&&!Y.props.touch,a=i(Y.props.duration,0,R.duration);if(t||e||n||r)return;if(et().hasAttribute("disabled"))return;if(at("onShow",[Y],!1),!1===Y.props.onShow(Y))return;Y.state.isVisible=!0,tt()&&($.style.visibility="visible");it(),dt(),Y.state.isMounted||($.style.transition="none");if(tt()){var u=rt(),p=u.box,c=u.content;w([p,c],0)}L=function(){var t;if(Y.state.isVisible&&!N){if(N=!0,$.offsetHeight,$.style.transition=Y.props.moveTransition,tt()&&Y.props.animation){var e=rt(),n=e.box,r=e.content;w([n,r],a),x([n,r],"visible")}st(),ut(),f(_,Y),null==(t=Y.popperInstance)||t.forceUpdate(),at("onMount",[Y]),Y.props.animation&&tt()&&function(t,e){mt(t,e)}(a,(function(){Y.state.isShown=!0,at("onShown",[Y])}))}},function(){var t,e=Y.props.appendTo,n=et();t=Y.props.interactive&&e===o||"parent"===e?n.parentNode:s(e,[n]);t.contains($)||t.appendChild($);Y.state.isMounted=!0,Ct()}()},hide:function(){var t=!Y.state.isVisible,e=Y.state.isDestroyed,n=!Y.state.isEnabled,r=i(Y.props.duration,1,R.duration);if(t||e||n)return;if(at("onHide",[Y],!1),!1===Y.props.onHide(Y))return;Y.state.isVisible=!1,Y.state.isShown=!1,N=!1,V=!1,tt()&&($.style.visibility="hidden");if(pt(),vt(),it(!0),tt()){var o=rt(),a=o.box,s=o.content;Y.props.animation&&(w([a,s],r),x([a,s],"hidden"))}st(),ut(),Y.props.animation?tt()&&function(t,e){mt(t,(function(){!Y.state.isVisible&&$.parentNode&&$.parentNode.contains($)&&e()}))}(r,Y.unmount):Y.unmount()},hideWithInteractivity:function(t){nt().addEventListener("mousemove",F),f(U,F),F(t)},enable:function(){Y.state.isEnabled=!0},disable:function(){Y.hide(),Y.state.isEnabled=!1},unmount:function(){Y.state.isVisible&&Y.hide();if(!Y.state.isMounted)return;Tt(),At().forEach((function(t){t._tippy.unmount()})),$.parentNode&&$.parentNode.removeChild($);_=_.filter((function(t){return t!==Y})),Y.state.isMounted=!1,at("onHidden",[Y])},destroy:function(){if(Y.state.isDestroyed)return;Y.clearDelayTimeouts(),Y.unmount(),bt(),delete e._tippy,Y.state.isDestroyed=!0,at("onDestroy",[Y])}};if(!P.render)return Y;var q=P.render(Y),$=q.popper,J=q.onUpdate;$.setAttribute("data-tippy-root",""),$.id="tippy-"+Y.id,Y.popper=$,e._tippy=Y,$._tippy=Y;var G=X.map((function(t){return t.fn(Y)})),K=e.hasAttribute("aria-expanded");return ht(),ut(),it(),at("onCreate",[Y]),P.showOnCreate&&Lt(),$.addEventListener("mouseenter",(function(){Y.props.interactive&&Y.state.isVisible&&Y.clearDelayTimeouts()})),$.addEventListener("mouseleave",(function(){Y.props.interactive&&Y.props.trigger.indexOf("mouseenter")>=0&&nt().addEventListener("mousemove",F)})),Y;function Q(){var t=Y.props.touch;return Array.isArray(t)?t:[t,0]}function Z(){return"hold"===Q()[0]}function tt(){var t;return!(null==(t=Y.props.render)||!t.$$tippy)}function et(){return D||e}function nt(){var t=et().parentNode;return t?E(t):document}function rt(){return B($)}function ot(t){return Y.state.isMounted&&!Y.state.isVisible||T.isTouch||y&&"focus"===y.type?0:i(Y.props.delay,t?0:1,R.delay)}function it(t){void 0===t&&(t=!1),$.style.pointerEvents=Y.props.interactive&&!t?"":"none",$.style.zIndex=""+Y.props.zIndex}function at(t,e,n){var r;(void 0===n&&(n=!0),G.forEach((function(n){n[t]&&n[t].apply(n,e)})),n)&&(r=Y.props)[t].apply(r,e)}function st(){var t=Y.props.aria;if(t.content){var n="aria-"+t.content,r=$.id;c(Y.props.triggerTarget||e).forEach((function(t){var e=t.getAttribute(n);if(Y.state.isVisible)t.setAttribute(n,e?e+" "+r:r);else{var o=e&&e.replace(r,"").trim();o?t.setAttribute(n,o):t.removeAttribute(n)}}))}}function ut(){!K&&Y.props.aria.expanded&&c(Y.props.triggerTarget||e).forEach((function(t){Y.props.interactive?t.setAttribute("aria-expanded",Y.state.isVisible&&t===et()?"true":"false"):t.removeAttribute("aria-expanded")}))}function pt(){nt().removeEventListener("mousemove",F),U=U.filter((function(t){return t!==F}))}function ct(t){if(!T.isTouch||!S&&"mousedown"!==t.type){var n=t.composedPath&&t.composedPath()[0]||t.target;if(!Y.props.interactive||!C($,n)){if(c(Y.props.triggerTarget||e).some((function(t){return C(t,n)}))){if(T.isTouch)return;if(Y.state.isVisible&&Y.props.trigger.indexOf("click")>=0)return}else at("onClickOutside",[Y,t]);!0===Y.props.hideOnClick&&(Y.clearDelayTimeouts(),Y.hide(),I=!0,setTimeout((function(){I=!1})),Y.state.isMounted||vt())}}}function ft(){S=!0}function lt(){S=!1}function dt(){var t=nt();t.addEventListener("mousedown",ct,!0),t.addEventListener("touchend",ct,r),t.addEventListener("touchstart",lt,r),t.addEventListener("touchmove",ft,r)}function vt(){var t=nt();t.removeEventListener("mousedown",ct,!0),t.removeEventListener("touchend",ct,r),t.removeEventListener("touchstart",lt,r),t.removeEventListener("touchmove",ft,r)}function mt(t,e){var n=rt().box;function r(t){t.target===n&&(O(n,"remove",r),e())}if(0===t)return e();O(n,"remove",A),O(n,"add",r),A=r}function gt(t,n,r){void 0===r&&(r=!1),c(Y.props.triggerTarget||e).forEach((function(e){e.addEventListener(t,n,r),z.push({node:e,eventType:t,handler:n,options:r})}))}function ht(){var t;Z()&&(gt("touchstart",yt,{passive:!0}),gt("touchend",xt,{passive:!0})),(t=Y.props.trigger,t.split(/\s+/).filter(Boolean)).forEach((function(t){if("manual"!==t)switch(gt(t,yt),t){case"mouseenter":gt("mouseleave",xt);break;case"focus":gt(n?"focusout":"blur",Et);break;case"focusin":gt("focusout",Et)}}))}function bt(){z.forEach((function(t){var e=t.node,n=t.eventType,r=t.handler,o=t.options;e.removeEventListener(n,r,o)})),z=[]}function yt(t){var e,n=!1;if(Y.state.isEnabled&&!Ot(t)&&!I){var r="focus"===(null==(e=y)?void 0:e.type);y=t,D=t.currentTarget,ut(),!Y.state.isVisible&&h(t)&&U.forEach((function(e){return e(t)})),"click"===t.type&&(Y.props.trigger.indexOf("mouseenter")<0||V)&&!1!==Y.props.hideOnClick&&Y.state.isVisible?n=!0:Lt(t),"click"===t.type&&(V=!n),n&&!r&&Dt(t)}}function wt(t){var e=t.target,n=et().contains(e)||$.contains(e);"mousemove"===t.type&&n||function(t,e){var n=e.clientX,r=e.clientY;return t.every((function(t){var e=t.popperRect,o=t.popperState,i=t.props.interactiveBorder,a=l(o.placement),s=o.modifiersData.offset;if(!s)return!0;var u="bottom"===a?s.top.y:0,p="top"===a?s.bottom.y:0,c="right"===a?s.left.x:0,f="left"===a?s.right.x:0,d=e.top-r+u>i,v=r-e.bottom-p>i,m=e.left-n+c>i,g=n-e.right-f>i;return d||v||m||g}))}(At().concat($).map((function(t){var e,n=null==(e=t._tippy.popperInstance)?void 0:e.state;return n?{popperRect:t.getBoundingClientRect(),popperState:n,props:P}:null})).filter(Boolean),t)&&(pt(),Dt(t))}function xt(t){Ot(t)||Y.props.trigger.indexOf("click")>=0&&V||(Y.props.interactive?Y.hideWithInteractivity(t):Dt(t))}function Et(t){Y.props.trigger.indexOf("focusin")<0&&t.target!==et()||Y.props.interactive&&t.relatedTarget&&$.contains(t.relatedTarget)||Dt(t)}function Ot(t){return!!T.isTouch&&Z()!==t.type.indexOf("touch")>=0}function Ct(){Tt();var n=Y.props,r=n.popperOptions,o=n.placement,i=n.offset,a=n.getReferenceClientRect,s=n.moveTransition,u=tt()?B($).arrow:null,p=a?{getBoundingClientRect:a,contextElement:a.contextElement||et()}:e,c=[{name:"offset",options:{offset:i}},{name:"preventOverflow",options:{padding:{top:2,bottom:2,left:5,right:5}}},{name:"flip",options:{padding:5}},{name:"computeStyles",options:{adaptive:!s}},{name:"$$tippy",enabled:!0,phase:"beforeWrite",requires:["computeStyles"],fn:function(t){var e=t.state;if(tt()){var n=rt().box;["placement","reference-hidden","escaped"].forEach((function(t){"placement"===t?n.setAttribute("data-placement",e.placement):e.attributes.popper["data-popper-"+t]?n.setAttribute("data-"+t,""):n.removeAttribute("data-"+t)})),e.attributes.popper={}}}}];tt()&&u&&c.push({name:"arrow",options:{element:u,padding:3}}),c.push.apply(c,(null==r?void 0:r.modifiers)||[]),Y.popperInstance=t.createPopper(p,$,Object.assign({},r,{placement:o,onFirstUpdate:L,modifiers:c}))}function Tt(){Y.popperInstance&&(Y.popperInstance.destroy(),Y.popperInstance=null)}function At(){return d($.querySelectorAll("[data-tippy-root]"))}function Lt(t){Y.clearDelayTimeouts(),t&&at("onTrigger",[Y,t]),dt();var e=ot(!0),n=Q(),r=n[0],o=n[1];T.isTouch&&"hold"===r&&o&&(e=o),e?p=setTimeout((function(){Y.show()}),e):Y.show()}function Dt(t){if(Y.clearDelayTimeouts(),at("onUntrigger",[Y,t]),Y.state.isVisible){if(!(Y.props.trigger.indexOf("mouseenter")>=0&&Y.props.trigger.indexOf("click")>=0&&["mouseleave","mousemove"].indexOf(t.type)>=0&&V)){var e=ot(!1);e?g=setTimeout((function(){Y.state.isVisible&&Y.hide()}),e):b=requestAnimationFrame((function(){Y.hide()}))}}else vt()}}function F(t,e){void 0===e&&(e={});var n=R.plugins.concat(e.plugins||[]);document.addEventListener("touchstart",L,r),window.addEventListener("blur",k);var o=Object.assign({},e,{plugins:n}),i=y(t).reduce((function(t,e){var n=e&&z(e,o);return n&&t.push(n),t}),[]);return g(t)?i[0]:i}F.defaultProps=R,F.setDefaultProps=function(t){Object.keys(t).forEach((function(e){R[e]=t[e]}))},F.currentInput=T;var W=Object.assign({},t.applyStyles,{effect:function(t){var e=t.state,n={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};Object.assign(e.elements.popper.style,n.popper),e.styles=n,e.elements.arrow&&Object.assign(e.elements.arrow.style,n.arrow)}}),X={mouseover:"mouseenter",focusin:"focus",click:"click"};var Y={name:"animateFill",defaultValue:!1,fn:function(t){var e;if(null==(e=t.props.render)||!e.$$tippy)return{};var n=B(t.popper),r=n.box,o=n.content,i=t.props.animateFill?function(){var t=m();return t.className="tippy-backdrop",x([t],"hidden"),t}():null;return{onCreate:function(){i&&(r.insertBefore(i,r.firstElementChild),r.setAttribute("data-animatefill",""),r.style.overflow="hidden",t.setProps({arrow:!1,animation:"shift-away"}))},onMount:function(){if(i){var t=r.style.transitionDuration,e=Number(t.replace("ms",""));o.style.transitionDelay=Math.round(e/10)+"ms",i.style.transitionDuration=t,x([i],"visible")}},onShow:function(){i&&(i.style.transitionDuration="0ms")},onHide:function(){i&&x([i],"hidden")}}}};var q={clientX:0,clientY:0},$=[];function J(t){var e=t.clientX,n=t.clientY;q={clientX:e,clientY:n}}var G={name:"followCursor",defaultValue:!1,fn:function(t){var e=t.reference,n=E(t.props.triggerTarget||e),r=!1,o=!1,i=!0,a=t.props;function s(){return"initial"===t.props.followCursor&&t.state.isVisible}function u(){n.addEventListener("mousemove",f)}function p(){n.removeEventListener("mousemove",f)}function c(){r=!0,t.setProps({getReferenceClientRect:null}),r=!1}function f(n){var r=!n.target||e.contains(n.target),o=t.props.followCursor,i=n.clientX,a=n.clientY,s=e.getBoundingClientRect(),u=i-s.left,p=a-s.top;!r&&t.props.interactive||t.setProps({getReferenceClientRect:function(){var t=e.getBoundingClientRect(),n=i,r=a;"initial"===o&&(n=t.left+u,r=t.top+p);var s="horizontal"===o?t.top:r,c="vertical"===o?t.right:n,f="horizontal"===o?t.bottom:r,l="vertical"===o?t.left:n;return{width:c-l,height:f-s,top:s,right:c,bottom:f,left:l}}})}function l(){t.props.followCursor&&($.push({instance:t,doc:n}),function(t){t.addEventListener("mousemove",J)}(n))}function d(){0===($=$.filter((function(e){return e.instance!==t}))).filter((function(t){return t.doc===n})).length&&function(t){t.removeEventListener("mousemove",J)}(n)}return{onCreate:l,onDestroy:d,onBeforeUpdate:function(){a=t.props},onAfterUpdate:function(e,n){var i=n.followCursor;r||void 0!==i&&a.followCursor!==i&&(d(),i?(l(),!t.state.isMounted||o||s()||u()):(p(),c()))},onMount:function(){t.props.followCursor&&!o&&(i&&(f(q),i=!1),s()||u())},onTrigger:function(t,e){h(e)&&(q={clientX:e.clientX,clientY:e.clientY}),o="focus"===e.type},onHidden:function(){t.props.followCursor&&(c(),p(),i=!0)}}}};var K={name:"inlinePositioning",defaultValue:!1,fn:function(t){var e,n=t.reference;var r=-1,o=!1,i=[],a={name:"tippyInlinePositioning",enabled:!0,phase:"afterWrite",fn:function(o){var a=o.state;t.props.inlinePositioning&&(-1!==i.indexOf(a.placement)&&(i=[]),e!==a.placement&&-1===i.indexOf(a.placement)&&(i.push(a.placement),t.setProps({getReferenceClientRect:function(){return function(t){return function(t,e,n,r){if(n.length<2||null===t)return e;if(2===n.length&&r>=0&&n[0].left>n[1].right)return n[r]||e;switch(t){case"top":case"bottom":var o=n[0],i=n[n.length-1],a="top"===t,s=o.top,u=i.bottom,p=a?o.left:i.left,c=a?o.right:i.right;return{top:s,bottom:u,left:p,right:c,width:c-p,height:u-s};case"left":case"right":var f=Math.min.apply(Math,n.map((function(t){return t.left}))),l=Math.max.apply(Math,n.map((function(t){return t.right}))),d=n.filter((function(e){return"left"===t?e.left===f:e.right===l})),v=d[0].top,m=d[d.length-1].bottom;return{top:v,bottom:m,left:f,right:l,width:l-f,height:m-v};default:return e}}(l(t),n.getBoundingClientRect(),d(n.getClientRects()),r)}(a.placement)}})),e=a.placement)}};function s(){var e;o||(e=function(t,e){var n;return{popperOptions:Object.assign({},t.popperOptions,{modifiers:[].concat(((null==(n=t.popperOptions)?void 0:n.modifiers)||[]).filter((function(t){return t.name!==e.name})),[e])})}}(t.props,a),o=!0,t.setProps(e),o=!1)}return{onCreate:s,onAfterUpdate:s,onTrigger:function(e,n){if(h(n)){var o=d(t.reference.getClientRects()),i=o.find((function(t){return t.left-2<=n.clientX&&t.right+2>=n.clientX&&t.top-2<=n.clientY&&t.bottom+2>=n.clientY})),a=o.indexOf(i);r=a>-1?a:r}},onHidden:function(){r=-1}}}};var Q={name:"sticky",defaultValue:!1,fn:function(t){var e=t.reference,n=t.popper;function r(e){return!0===t.props.sticky||t.props.sticky===e}var o=null,i=null;function a(){var s=r("reference")?(t.popperInstance?t.popperInstance.state.elements.reference:e).getBoundingClientRect():null,u=r("popper")?n.getBoundingClientRect():null;(s&&Z(o,s)||u&&Z(i,u))&&t.popperInstance&&t.popperInstance.update(),o=s,i=u,t.state.isMounted&&requestAnimationFrame(a)}return{onMount:function(){t.props.sticky&&a()}}}};function Z(t,e){return!t||!e||(t.top!==e.top||t.right!==e.right||t.bottom!==e.bottom||t.left!==e.left)}return e&&function(t){var e=document.createElement("style");e.textContent=t,e.setAttribute("data-tippy-stylesheet","");var n=document.head,r=document.querySelector("head>style,head>link");r?n.insertBefore(e,r):n.appendChild(e)}('.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}'),F.setDefaultProps({plugins:[Y,G,K,Q],render:N}),F.createSingleton=function(t,e){var n;void 0===e&&(e={});var r,o=t,i=[],a=[],s=e.overrides,u=[],f=!1;function l(){a=o.map((function(t){return c(t.props.triggerTarget||t.reference)})).reduce((function(t,e){return t.concat(e)}),[])}function d(){i=o.map((function(t){return t.reference}))}function v(t){o.forEach((function(e){t?e.enable():e.disable()}))}function g(t){return o.map((function(e){var n=e.setProps;return e.setProps=function(o){n(o),e.reference===r&&t.setProps(o)},function(){e.setProps=n}}))}function h(t,e){var n=a.indexOf(e);if(e!==r){r=e;var u=(s||[]).concat("content").reduce((function(t,e){return t[e]=o[n].props[e],t}),{});t.setProps(Object.assign({},u,{getReferenceClientRect:"function"==typeof u.getReferenceClientRect?u.getReferenceClientRect:function(){var t;return null==(t=i[n])?void 0:t.getBoundingClientRect()}}))}}v(!1),d(),l();var b={fn:function(){return{onDestroy:function(){v(!0)},onHidden:function(){r=null},onClickOutside:function(t){t.props.showOnCreate&&!f&&(f=!0,r=null)},onShow:function(t){t.props.showOnCreate&&!f&&(f=!0,h(t,i[0]))},onTrigger:function(t,e){h(t,e.currentTarget)}}}},y=F(m(),Object.assign({},p(e,["overrides"]),{plugins:[b].concat(e.plugins||[]),triggerTarget:a,popperOptions:Object.assign({},e.popperOptions,{modifiers:[].concat((null==(n=e.popperOptions)?void 0:n.modifiers)||[],[W])})})),w=y.show;y.show=function(t){if(w(),!r&&null==t)return h(y,i[0]);if(!r||null!=t){if("number"==typeof t)return i[t]&&h(y,i[t]);if(o.indexOf(t)>=0){var e=t.reference;return h(y,e)}return i.indexOf(t)>=0?h(y,t):void 0}},y.showNext=function(){var t=i[0];if(!r)return y.show(0);var e=i.indexOf(r);y.show(i[e+1]||t)},y.showPrevious=function(){var t=i[i.length-1];if(!r)return y.show(t);var e=i.indexOf(r),n=i[e-1]||t;y.show(n)};var x=y.setProps;return y.setProps=function(t){s=t.overrides||s,x(t)},y.setInstances=function(t){v(!0),u.forEach((function(t){return t()})),o=t,v(!1),d(),l(),u=g(y),y.setProps({triggerTarget:a})},u=g(y),y},F.delegate=function(t,e){var n=[],o=[],i=!1,a=e.target,s=p(e,["target"]),u=Object.assign({},s,{trigger:"manual",touch:!1}),f=Object.assign({touch:R.touch},s,{showOnCreate:!0}),l=F(t,u);function d(t){if(t.target&&!i){var n=t.target.closest(a);if(n){var r=n.getAttribute("data-tippy-trigger")||e.trigger||R.trigger;if(!n._tippy&&!("touchstart"===t.type&&"boolean"==typeof f.touch||"touchstart"!==t.type&&r.indexOf(X[t.type])<0)){var s=F(n,f);s&&(o=o.concat(s))}}}}function v(t,e,r,o){void 0===o&&(o=!1),t.addEventListener(e,r,o),n.push({node:t,eventType:e,handler:r,options:o})}return c(l).forEach((function(t){var e=t.destroy,a=t.enable,s=t.disable;t.destroy=function(t){void 0===t&&(t=!0),t&&o.forEach((function(t){t.destroy()})),o=[],n.forEach((function(t){var e=t.node,n=t.eventType,r=t.handler,o=t.options;e.removeEventListener(n,r,o)})),n=[],e()},t.enable=function(){a(),o.forEach((function(t){return t.enable()})),i=!1},t.disable=function(){s(),o.forEach((function(t){return t.disable()})),i=!0},function(t){var e=t.reference;v(e,"touchstart",d,r),v(e,"mouseover",d),v(e,"focusin",d),v(e,"click",d)}(t)})),l},F.hideAll=function(t){var e=void 0===t?{}:t,n=e.exclude,r=e.duration;_.forEach((function(t){var e=!1;if(n&&(e=b(n)?t.reference===n:t.popper===n.popper),!e){var o=t.props.duration;t.setProps({duration:r}),t.hide(),t.state.isDestroyed||t.setProps({duration:o})}}))},F.roundArrow='',F})); +//# sourceMappingURL=tippy-bundle.umd.min.js.map diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index b584063..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "ES2020", - "outDir": "out", - "lib": [ - "ES2020", - "es2021", - "DOM" - ], - "sourceMap": true, - "allowJs": true, - "rootDir": "src", - "strict": true /* enable all strict type-checking options */, - "skipLibCheck": true, - - /* Additional Checks */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - }, - "exclude": [ - "scripts/**/*", - "out/**/*", - "node_modules/**/*" - ] - -} diff --git a/vsc-extension-quickstart.md b/vsc-extension-quickstart.md deleted file mode 100644 index 04a57fc..0000000 --- a/vsc-extension-quickstart.md +++ /dev/null @@ -1,42 +0,0 @@ -# Welcome to your VS Code Extension - -## What's in the folder - -* This folder contains all of the files necessary for your extension. -* `package.json` - this is the manifest file in which you declare your extension and command. - * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. -* `src/extension.ts` - this is the main file where you will provide the implementation of your command. - * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. - * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. - -## Get up and running straight away - -* Press `F5` to open a new window with your extension loaded. -* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. -* Set breakpoints in your code inside `src/extension.ts` to debug your extension. -* Find output from your extension in the debug console. - -## Make changes - -* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. -* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. - -## Explore the API - -* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. - -## Run tests - -* Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`. -* Press `F5` to run the tests in a new window with your extension loaded. -* See the output of the test result in the debug console. -* Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder. - * The provided test runner will only consider files matching the name pattern `**.test.ts`. - * You can create folders inside the `test` folder to structure your tests any way you want. - -## Go further - -* [Follow UX guidelines](https://code.visualstudio.com/api/ux-guidelines/overview) to create extensions that seamlessly integrate with VS Code's native interface and patterns. - * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). - * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace. - * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).