├── .eslintrc.json ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── assets ├── clean-example.gif ├── clean_generate_flutter.gif ├── generate_class_flutter.gif ├── generate_folder_3-tiers.gif ├── generate_folder_MVC.gif ├── generate_folder_test_flutter.gif ├── generate_interface_flutter.gif ├── implements_class_flutter.gif ├── wrap-with-consumer.gif └── wrap-with-value-listener.gif ├── jsconfig.json ├── logo.png ├── package-lock.json ├── package.json ├── snippets ├── aqueduct.json ├── cubit.json ├── dart.json ├── dart │ ├── dart2.json │ └── dart3.json ├── dio.json ├── flutter.json ├── flutter │ ├── flutter2.17.json │ ├── flutter2.json │ └── flutter3.10.json ├── flutter_bloc.json ├── getx.json ├── json_serializable.json ├── mobx.json ├── mockito.json ├── modular.json ├── modular_old.json ├── provider.json └── shelf.json ├── src ├── commands │ ├── clean_arch_folders.js │ ├── clean_arch_folders_for_flutter.js │ ├── create_file.js │ ├── create_getter.js │ ├── fvm_configure.js │ ├── fvm_install_configure.js │ ├── generate_class.js │ ├── generate_construtor.js │ ├── generate_copy_with.js │ ├── generate_interface.js │ ├── generate_singleton_class.js │ ├── generate_stateful_widget.js │ ├── generate_stateless_widget.js │ ├── generate_test_file.js │ ├── getx_new_feature.js │ ├── implements_interface.js │ ├── import_gist.js │ ├── inherit_class.js │ ├── json_serializable_generate_json_key.js │ ├── modular_initial_config.js │ ├── modular_new_feature.js │ ├── mvc_feature.js │ ├── snake_case_transform.js │ ├── templates │ │ ├── dart │ │ │ ├── class_implements.template │ │ │ └── inherit_class.template │ │ ├── fvm │ │ │ └── settings.template │ │ ├── modular │ │ │ ├── app_module.template │ │ │ ├── app_widget.template │ │ │ ├── home_page.template │ │ │ └── main.template │ │ └── read_file_template.js │ ├── three_tiers.js │ └── wrap-with.js ├── extension.js └── utils │ ├── class_content_helper.js │ ├── get-class-content.js │ ├── get-selected-text.js │ ├── getDartSdkVersion.js │ └── wrap-with.js ├── test ├── runTest.js └── suite │ ├── extension.test.js │ └── index.js └── vsc-extension-quickstart.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": false, 4 | "commonjs": true, 5 | "es6": true, 6 | "node": true, 7 | "mocha": true 8 | }, 9 | "parserOptions": { 10 | "ecmaVersion": 2018, 11 | "ecmaFeatures": { 12 | "jsx": true 13 | }, 14 | "sourceType": "module" 15 | }, 16 | "rules": { 17 | "no-const-assign": "warn", 18 | "no-this-before-super": "warn", 19 | "no-undef": "warn", 20 | "no-unreachable": "warn", 21 | "no-unused-vars": "warn", 22 | "constructor-super": "warn", 23 | "valid-typeof": "warn" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode-test/ 3 | *.vsix 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ] 16 | }, 17 | { 18 | "name": "Extension Tests", 19 | "type": "extensionHost", 20 | "request": "launch", 21 | "runtimeExecutable": "${execPath}", 22 | "args": [ 23 | "--extensionDevelopmentPath=${workspaceFolder}", 24 | "--extensionTestsPath=${workspaceFolder}/test/suite/index" 25 | ] 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.enableFiletypes": [ 3 | "javascript" 4 | ] 5 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | test/** 4 | .gitignore 5 | vsc-extension-quickstart.md 6 | **/jsconfig.json 7 | **/*.map 8 | **/.eslintrc.json 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "flutter-dart-utils" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | # Releases 8 | ## [1.8.7] 9 | - change: FVM 3.0 10 | 11 | ## [1.8.6] 12 | - fix: regex getFields 13 | 14 | 15 | ## [1.8.5] 16 | - fix: duplicate import material when create copyWith method 17 | 18 | 19 | ## [1.8.4] 20 | - fix: 21 | - regex GenerateConstructor and Generate CopyWith 22 | - Show 'GenerateConstructor' and 'GenerateCopyWith' commands only if the user is on a class declaration line. 23 | 24 | 25 | ## [1.8.3] 26 | - fix: regex copyWith and Generator Contructor 27 | 28 | ## [1.8.2] 29 | - fix: copyWith with ValueGetter and formatCode 30 | 31 | 32 | ## [1.8.1] 33 | - fix: regex find fields 34 | 35 | ## [1.8.0] 36 | - feat: Add commands: 37 | - Generate Constructor with named params 38 | - Generate Copy With 39 | 40 | 41 | ## [1.7.1] 42 | - fix: generate Getter e Add JsonKey from json_serializable 43 | 44 | ## [1.7.0] 45 | - feat: Add commands: 46 | - Snake Case Transform 47 | - Add JsonKey from json_serializable 48 | - Generate Getter 49 | 50 | 51 | ## [1.6.0] 52 | - feat: add json_serializable snippet 53 | 54 | ## [1.4.0] 55 | - feat: add snippet WidgetsBinding.instance.addPostFrameCallback 56 | 57 | 58 | ## [1.3.0] 59 | - feat: mixin suporte 60 | - refactor: template singleton class 61 | 62 | ## [1.2.1] 63 | - fix: placeholder fvm install and configure 64 | 65 | 66 | ## [1.2.0] 67 | - New Feature: Add feature fvm configure 68 | 69 | ## [1.1.2] 70 | - BugFix: identify folder separator bar based on operating system 71 | 72 | 73 | ## [1.1.1] 74 | - BugFix: Wraps commands not found 75 | 76 | 77 | ## [1.1.0] 78 | - Configure the FVM within the project 79 | 80 | ## [1.0.5] 81 | - BugFix: erro to load pubspec.yaml 82 | 83 | ## [1.0.4] 84 | - BugFix: the snippet loading path 85 | 86 | ## [1.0.3] 87 | - Change icon 88 | 89 | ## [1.0.1] 90 | - Add icon 91 | 92 | ## [1.0.0] 93 | - Now the extension understands which version of dart you are working on to adapt to the new semantics of dart 3. There is no need to have multiple snippets anymore. 94 | 95 | - In this version we made the adaptation for the snippets: 96 | * **dart** 97 | * **flutter** 98 | 99 | - Command: 100 | * **Implements Interface** 101 | 102 | - For those who use dart 3 we added one more command: 103 | * **Extends Class** and with it you can have an abstract class extended into a new implementation class 104 | 105 | 106 | ----- 107 | # Old Versions 108 | 109 | ## [0.0.34] 110 | - Add snippets for mockito 111 | ## [0.0.35] 112 | - Restructuring clean architecture folder generation 113 | ## [0.0.36] 114 | - New mockito snippet 115 | ## [0.0.39] 116 | - 3-Tiers Folders 117 | ## [0.0.40] 118 | - Bug fix StatefulWidget generate 119 | ## [0.0.41] 120 | - Bug fix Implements Interface 121 | ## [0.0.42] 122 | - Bug fix folder for clean architecture 123 | ## [0.0.44] 124 | - Add news modular snipets 125 | ## [0.0.45] 126 | - MVC new features 127 | ## [0.0.46] 128 | 129 | - Add Wrap with Consumer(Provider) and ValueListenableBuilder 130 | - New Snippets ChangeNotifier 131 | - New Snippets ValueNotifier 132 | - Change Snippets Modular 133 | ## [0.0.56] 134 | - Add Provider Snippets 135 | ## [0.0.57] 136 | - Add Flutter Snippet TextEditingController 137 | ## [0.0.59] 138 | - Add GetX Snippets 139 | ## [0.0.63] 140 | - Add Wrap with Observer(MobX) 141 | ## [0.0.64] 142 | - Add Shelf Snippets 143 | ## [0.0.65] 144 | - Bugfix Shelf controller Snippets 145 | ## [0.0.66] 146 | - Add new snippets from GetX 147 | ## [0.0.67] 148 | - Add new snippets from GetX GetView 149 | ## [0.0.68] 150 | - Add new snippets from Modular3 151 | ## [0.0.71] 152 | - GetX create new feature 153 | ## [0.0.73] 154 | - Mysql Connection template 155 | ## [0.0.74] 156 | - New snippets of test 157 | ## [0.0.75] 158 | - Bugfix- snippets group test 159 | ## [0.0.76] 160 | - Code Review, refatoring and add new features 161 | ## [0.0.77] 162 | - Bugfix on windows system 163 | ## [0.0.78] 164 | - Bugfix on windows system for implementation interface 165 | ## [0.0.79] 166 | - Add wrap with Obx e GetX 167 | ## [0.0.81] 168 | - Constructor snippet, and bugfix any snippets 169 | ## [0.0.82] 170 | - Change snippets Flutter modular 3 171 | ## [0.0.83] 172 | - Mobx Snippets 173 | ## [0.0.84] 174 | - Add new snippet (private constructor) 175 | ## [0.0.85] 176 | - Add new snippet (class exception) 177 | ## [0.0.86] 178 | - bugfix mobxstore generate 179 | ## [0.0.89] 180 | - add key on flutter snippets 181 | ## [0.0.91] 182 | - add 'const' in flutter e getx snippets 183 | ## [0.0.92] 184 | - add Create Stateless Widget e Create Stateful Widget on menu 185 | ## [0.0.93] 186 | - add 'const' in getxPage snippets 187 | ## [0.0.94] 188 | - add template to create static attributes 189 | ## [0.0.95] 190 | - add template to create SizedBox separator 191 | ## [0.0.96] 192 | - add template to create GlobalKey 193 | ## [0.0.97] 194 | - lint fix createState (library_private_types_in_public_api) 195 | ## [0.0.98] 196 | - lint fix MobxStore (library_private_types_in_public_api) 197 | ## [0.0.103] 198 | - Fix create commands 199 | ## [0.0.104] 200 | - Add new snippets dart 201 | ## [0.0.105] 202 | - Create a new snippet to create singleton class 203 | 204 | ## [0.1.] 205 | - Add snippet for create a part code based a filename ex: home_controller.dart -> home_controller.g.dart 206 | 207 | ## [0.2.0] 208 | - Add snippets 209 | - fu-stls create StatelessWidget with super.key 210 | - fu-stfs create StatefulWidget with super.key 211 | 212 | ## [0.2.1] 213 | - Bugfix shotcut snippets fu-stls 214 | 215 | ## [0.3.0] 216 | - New snippets Flutter (fu-mediaquery, fu-sw, fu-sh) 217 | 218 | ## [0.3.1] 219 | - Fix snippet fu-sw, fu-sh 220 | 221 | ## [0.4.0] 222 | - New snippets Flutter (fu-navigator) 223 | 224 | ## [0.4.1] 225 | - New snippets Flutter (fu-snackbar) 226 | - Bugfix implements interface 227 | 228 | ## [0.4.3] 229 | - Bugfix implements interface 230 | 231 | ## [0.4.4] 232 | - Bugfix implements interface write spaces 233 | 234 | ## [0.4.5] 235 | - Bugfix implements interface without write spaces 236 | 237 | ## [0.5.0] 238 | - Changing fu-modular to fu-modular-old-* to maintain compatibility with the previous version. 239 | - Now, fu-modular-* has been replaced to meet the latest version of the modular. 240 | 241 | ## [0.5.1] 242 | - Correction in the modular documentation 243 | 244 | ## [0.6.0] 245 | - Added the automatic configuration of the modular flutter by right-clicking the lib and accessing the menu Flutter Modular: Configure Framework 246 | 247 | ## [0.6.1] 248 | - Fix on create AppWiget on Flutter Modular: Configure Framework 249 | 250 | ## [0.7.0] 251 | - add dio snippets 252 | 253 | ## [0.8.0] 254 | - add snippet fu-zero-delay 255 | 256 | ## [0.8.1] 257 | - remove const variable in fu-zero-delay 258 | 259 | ## [0.8.2] 260 | - added snippet for flutter modular bind.lazySingleton with interface and following clean code pattern 261 | 262 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Rodrigo Rahman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build-package: 2 | vsce package 3 | vsce publish 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter-dart-utils README 2 | 3 | Extension that assists in the creation of tests, interfaces, classes and to work with clean architecture, 3-tiers or MVC having the possibility to create features and create tests folder. 4 | 5 | * Dart Snippets 6 | * Flutter Snippets 7 | * Modular Snippets 8 | * Modular-old Snippets 9 | * Mobx Snippets 10 | * Cubit Snippets 11 | * flutter_bloc Snippets 12 | * Mockito Snippets 13 | * GetX Snippets 14 | * Shelf Snippets 15 | * Dio Snippets 16 | 17 | ## Installation 18 | Flutter Utils can be installed from the [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=RodrigoRahman.flutter-dart-utils) or by [searching within VSCode](https://code.visualstudio.com/docs/editor/extension-gallery#_search-for-an-extension). 19 | 20 | ## Youtube movie for examples 21 | [Youtube](https://youtu.be/YlL0KJhDFEM) (https://youtu.be/YlL0KJhDFEM) 22 | ## Features Wrap With 23 | ***Important!!!*** 24 | Select the full widget to find these options 25 | 26 | | Features Wrap With | 27 | | ------------------------------------ | 28 | | `Wrap with LayoutBuilder` | 29 | | `Wrap with Builder` | 30 | | `Wrap with ValueListenableBuilder` | 31 | | `Wrap with Consumer` | 32 | | `Wrap with MobX Observer` | 33 | | `Wrap with Obx` | 34 | | `Wrap with Getx` | 35 | | `Wrap with Watch of Signals` | 36 | 37 | 38 | ## Menu Features: 39 | | Menu Features | 40 | | ------------------------------------ | 41 | | `Clean Arch.: New Feature Backend` | 42 | | `Clean Arch.: New Feature Flutter` | 43 | | `3-Tiers Back: New Feature` | 44 | | `Create Dart Interface` | 45 | | `Create Dart Class` | 46 | | `Create Stateless Widget` | 47 | | `Create Stateful Widget` | 48 | | `GetX: New Feature` | 49 | | `Flutter Modular: New Feature` | 50 | 51 | 52 | ## Dart Snippets Usage 53 | 54 | | Shortcut | Description | 55 | | -------------------------------- | ------------------------------------------------------ | 56 | | `fu-freezed` | Creates a Freezed class | 57 | | `fu-freezed-json-serializable` | Creates a Freezed with JsonSerializable | 58 | | `fu-interface` | Creates a Interfaces | 59 | | `fu-class-interface` | Creates a Classes with interface | 60 | | `fu-callable-class` | Create a Callable Classes | 61 | | `fu-d-test-init` | Create a dart tests | 62 | | `fu-class` | Create class with file name | 63 | | `fu-class-singleton` | Create a singleton class with file name | 64 | | `fu-class-equatable` | Create class with file name and add Equatable | 65 | | `fu-constructor` | Create constructor with file name based | 66 | | `fu-private-constructor` | Create private constructor with file name based | 67 | | `fu-static-attribute` | Create static atribute in class | 68 | | `fu-zero-delay` | Create Future.delayed zero | 69 | | `fu-seconds-delay` | Create Future.delayed in seconds | 70 | | `fu-milliseconds-delay` | Create Future.delayed in milliseconds | 71 | | `fu-mixin` | Create mixin with file name | 72 | | `fu-enum` | Create enum with file name | 73 | | `fu-extension` | Create extension with file name | 74 | 75 | 76 | ## Flutter Snippets Usage 77 | | Shortcut | Description | 78 | | -------------------------------- | ---------------------------------------------------- | 79 | | `fu-stl` | Create StatelessWidget with Scaffold and AppBar | 80 | | `fu-stls` | Create StatelessWidget with super.key, Scaffold and AppBar | 81 | | `fu-stf` | Create StatefulWidget with Scaffold and AppBar | 82 | | `fu-stfs` | Create StatefulWidget with with super.key, Scaffold and AppBar | 83 | | `fu-f-test-init` | Create a dart tests | 84 | | `fu-change-notifier` | Create change notifier class | 85 | | `fu-value-notifier` | Create ValueNotifier | 86 | | `fu-text-editing-controller` | Create TextEditingController | 87 | | `fu-separator` | Create SizedBox separator | 88 | | `fu-form-key` | Create formKey GlobalKey | 89 | | `fu-part` | Add a part based file name ex: home_controller -> home_controller.g.dart | 90 | | `fu-mediaquery` | Put MediaQuery.of | 91 | | `fu-sw` | Get Screen size width from MediaQuery | 92 | | `fu-sh` | Get Screen size height from MediaQuery | 93 | | `fu-navigator` | Put Navigator.of(context). | 94 | | `fu-snackbar` | Put ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('$1'))) | 95 | | `fu-postframecallback` | Put WidgetsBinding.instance.addPostFrameCallback | 96 | 97 | ## Aqueduct Snippets Usage 98 | 99 | | Shortcut | Description | 100 | | -------------------------------- | ---------------------------------------------------- | 101 | | `fu-aqu-operation` | Creates aqueduct operation | 102 | | `fu-aqu-serializable` | Creates aqueduct class serializable | 103 | 104 | 105 | ## Json Serializable 106 | 107 | | Shortcut | Description | 108 | | -------------------------------- | ---------------------------------------------------- | 109 | | `fu-class-json-serializable` | Generate class with json_serializable pattern | 110 | 111 | ## Modular Old Version Snippets Usage 112 | 113 | | Shortcut | Description | 114 | | -------------------------------- | ---------------------------------------------------- | 115 | | `fu-modular-old-router-child` | Creates router with page | 116 | | `fu-modular-old-router` | Creates router module | 117 | | `fu-modular-old-initial-router-module` | Creates router module with Modular.initialRoute | 118 | | `fu-modular-old-initial-router-child` | Creates router page with Modular.initialRoute | 119 | | `fu-modular-old-bind` | Create Bind for modular | 120 | | `fu-modular-old_codegen_inject` | Modular codegen inject | 121 | | `fu-modular-old_module` | Create Module | 122 | 123 | ## Modular Snippets Usage 124 | | Shortcut | Description | 125 | | -------------------------------- | -------------------------------------------------------------------- | 126 | | `fu-modular-initial-config` | Create a initial config main.dart | 127 | | `fu-modular-app-widget` | Create a initial config main.dart | 128 | | `fu-modular-router-child` | Creates router with page | 129 | | `fu-modular-router` | Creates router module | 130 | | `fu-modular-initial-router-child` | Creates router page with Modular.initialRoute | 131 | | `fu-modular-bind-factory` | Create Bind Factory for modular | 132 | | `fu-modular-bind-factory-cc` | Create Bind Factory for modular with interface and clean code pattern | 133 | | `fu-modular-bind-instance` | Create Bind Instance for modular | 134 | | `fu-modular-bind-instance-cc` | Create Bind Instance for modular with interface and clean code pattern | 135 | | `fu-modular-bind-singleton` | Create Bind Singleton for modular | 136 | | `fu-modular-bind-lazySingleton` | Create Bind Lazy Singleton for modular with interface | 137 | | `fu-modular-bind-lazySingleton-cc` | Create Bind Lazy Singleton for modular with interface and clean code pattern | 138 | | `fu-modular-bind-factory-interface` | Create Bind Factory for modular with interface | 139 | | `fu-modular-bind-instance-interface` | Create Bind Instance for modular with interface | 140 | | `fu-modular-bind-singleton-interface` | Create Bind Singleton for modular with interface | 141 | | `fu-modular-bind-lazySingleton-interface` | Create Bind Lazy Singleton for modular with interface | 142 | | `fu-modular_module` | Create Module | 143 | 144 | 145 | ## Flutter Bloc Snippets Usage 146 | 147 | | Shortcut | Description | 148 | | -------------------------------- | ---------------------------------------------------- | 149 | | `fu-bloctransform` | Override transformEvents method | 150 | 151 | 152 | ## Cubit Snippets Usage 153 | 154 | | Shortcut | Description | 155 | | -------------------------------- | ---------------------------------------------------- | 156 | | `fu-cubitot` | Override onTransition method | 157 | | `fu-cubitaction` | Create cubit function action | 158 | 159 | 160 | ## Mockito Snippets Usage 161 | 162 | | Shortcut | Description | 163 | | -------------------------------- | ---------------------------------------------------- | 164 | | `fu-test-when-async` | Add when mockito async | 165 | | `fu-test-when` | Add when mockito sync | 166 | | `fu-test-when-throw` | Add when mockito sync | 167 | | `fu-test-mock` | Create a mock class | 168 | 169 | ## Flutter Provider Snippets Usage 170 | 171 | | Shortcut | Description | 172 | | -------------------------------- | ---------------------------------------------------- | 173 | | `fu-provider-watch` | context.watch | 174 | | `fu-provider-read` | context.watch | 175 | | `fu-provider-select` | context.select | 176 | 177 | 178 | ## Flutter GetX Snippets Usage 179 | 180 | | Shortcut | Description | 181 | | -------------------------------- | ---------------------------------------------------- | 182 | | `fu-getxbinding` | Create Binding | 183 | | `fu-getxcontroller` | Create Controller | 184 | | `fu-getxrx` | Create Rx variable | 185 | | `fu-getxobs` | Create .obs variable | 186 | | `fu-getxoninit` | Create onInit method | 187 | | `fu-getxonclose` | Create onClose method | 188 | | `fu-getxpage` | Create Page with GetView | 189 | 190 | 191 | ## Shelf/Shelf-Router Snippets Usage 192 | 193 | | Shortcut | Description | 194 | | -------------------------------- | ---------------------------------------------------- | 195 | | `fu-shelf-controller` | Create Controller with shelf-router | 196 | | `fu-shelf-operation` | Create Rest Operation | 197 | 198 | ## Dio Snippets Usage 199 | 200 | | Shortcut | Description | 201 | | -------------------------------- | ---------------------------------------------------- | 202 | | `fu-dio-template-request` | Template for repositories | 203 | 204 | 205 | ### Generate folders for MVC architecture 206 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/generate_folder_MVC.gif) 207 | 208 | ### Generate dart interface 209 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/generate_interface_flutter.gif) 210 | 211 | ### Generate dart class 212 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/generate_class_flutter.gif) 213 | 214 | ### Implements dart interface 215 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/implements_class_flutter.gif) 216 | 217 | ### Generate folders clean architecture for backend 218 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/clean-example.gif) 219 | 220 | ### Generate folders clean architecture for flutter 221 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/clean_generate_flutter.gif) 222 | 223 | ### Generate folders 3-tiers architecture 224 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/generate_folder_3-tiers.gif) 225 | 226 | ### Generate folder for test 227 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/generate_folder_test_flutter.gif) 228 | 229 | ### Wrap with Consumer 230 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/wrap-with-consumer.gif) 231 | 232 | ### Wrap with ValueListenableBuilder 233 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/wrap-with-value-listener.gif) 234 | 235 | ### Wrap with Builder 236 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/wrap-with-value-listener.gif) 237 | 238 | ### Wrap with LayoutBuilder 239 | ![demo](https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/master/assets/wrap-with-value-listener.gif) 240 | 241 | 242 | 243 | 244 | ## Requirements 245 | 246 | 247 | ## Extension Settings 248 | 249 | 250 | ## Known Issues -------------------------------------------------------------------------------- /assets/clean-example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/clean-example.gif -------------------------------------------------------------------------------- /assets/clean_generate_flutter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/clean_generate_flutter.gif -------------------------------------------------------------------------------- /assets/generate_class_flutter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/generate_class_flutter.gif -------------------------------------------------------------------------------- /assets/generate_folder_3-tiers.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/generate_folder_3-tiers.gif -------------------------------------------------------------------------------- /assets/generate_folder_MVC.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/generate_folder_MVC.gif -------------------------------------------------------------------------------- /assets/generate_folder_test_flutter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/generate_folder_test_flutter.gif -------------------------------------------------------------------------------- /assets/generate_interface_flutter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/generate_interface_flutter.gif -------------------------------------------------------------------------------- /assets/implements_class_flutter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/implements_class_flutter.gif -------------------------------------------------------------------------------- /assets/wrap-with-consumer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/wrap-with-consumer.gif -------------------------------------------------------------------------------- /assets/wrap-with-value-listener.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/assets/wrap-with-value-listener.gif -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "checkJs": true, /* Typecheck .js files. */ 6 | "lib": [ 7 | "es6", 8 | "es5", 9 | ] 10 | }, 11 | "include": ["src"], 12 | "exclude": [ 13 | "node_modules" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutter-dart-utils", 3 | "displayName": "Flutter & Dart Utilities", 4 | "description": "Official package of Academia do Flutter (BR) the best flutter course in Brazil", 5 | "publisher": "RodrigoRahman", 6 | "homepage": "http://academiadoflutter.com.br", 7 | "author": { 8 | "name": "Rodrigo Rahman GDE Flutter & Dart", 9 | "email": "rodrigorahman@academiadoflutter.com.br", 10 | "url": "http://academiadoflutter.com.br" 11 | }, 12 | "version": "1.8.7", 13 | "bugs": { 14 | "url": "https://github.com/rodrigorahman/flutter-dart-utils-vscode/issues", 15 | "email": "rodrigorahman@academiadoflutter.com.br" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/rodrigorahman/flutter-dart-utils-vscode" 20 | }, 21 | "engines": { 22 | "vscode": "^1.46.0" 23 | }, 24 | "keywords": [ 25 | "dart", 26 | "flutter", 27 | "clean architecture", 28 | "mobx", 29 | "getx", 30 | "bloc" 31 | ], 32 | "categories": [ 33 | "Snippets", 34 | "Programming Languages" 35 | ], 36 | "activationEvents": [ 37 | "onCommand:extension.clean-architecture-folders", 38 | "onCommand:extension.extension.getxfeature", 39 | "onCommand:extension.extension.modularfeature", 40 | "onCommand:extension.extension.extension.modulariniital", 41 | "workspaceContains:**/pubspec.yaml" 42 | ], 43 | "main": "./src/extension.js", 44 | "icon": "logo.png", 45 | "contributes": { 46 | "configuration": [ 47 | { 48 | "title": "Flutter & Dart Utilities", 49 | "properties": { 50 | "generate.template.type": { 51 | "type": "string", 52 | "default": "I Prefix", 53 | "description": "Choose the pattern that the extension will generate your classes", 54 | "enum": [ 55 | "Clean Code", 56 | "Clean Code choice suffix", 57 | "I Prefix" 58 | ], 59 | "enumDescriptions": [ 60 | "Use prefix I in the interfaces and remove the I when implementing the class", 61 | "Use the clean code standard to create the interfaces and classes and choice a suffix class name", 62 | "Use the clean code standard to create the interfaces and classes" 63 | ] 64 | } 65 | } 66 | } 67 | ], 68 | "commands": [ 69 | { 70 | "command": "extension.clean-architecture-folders", 71 | "title": "Clean Arch.: New Feature Backend " 72 | }, 73 | { 74 | "command": "extension.clean-architecture-folders-for-flutter", 75 | "title": "Clean Arch.: New Feature Flutter " 76 | }, 77 | { 78 | "command": "extension.3-tiers", 79 | "title": "3-Tiers Back: New Feature " 80 | }, 81 | { 82 | "command": "extension.mvc-feature", 83 | "title": "MVC: New Feature " 84 | }, 85 | { 86 | "command": "extension.generateTestFile", 87 | "title": "Generate Test Folder" 88 | }, 89 | { 90 | "command": "extension.generateInterface", 91 | "title": "Create Dart Interface" 92 | }, 93 | { 94 | "command": "extension.generateClass", 95 | "title": "Create Dart Class" 96 | }, 97 | { 98 | "command": "extension.generateSingletonClass", 99 | "title": "Create Dart Singleton Class" 100 | }, 101 | { 102 | "command": "extension.generateStatelessWidget", 103 | "title": "Create Stateless Widget" 104 | }, 105 | { 106 | "command": "extension.generateStatefulWidget", 107 | "title": "Create Stateful Widget" 108 | }, 109 | { 110 | "command": "extension.implementsInterface", 111 | "title": "Implements interface" 112 | }, 113 | { 114 | "command": "extension.generateGetter", 115 | "title": "Generate Getter" 116 | }, 117 | { 118 | "command": "extension.fu-wrap-with-value-notifier", 119 | "title": "Wrap with ValueListenableBuilder" 120 | }, 121 | { 122 | "command": "extension.fu-wrap-with-consumer", 123 | "title": "Wrap with Consumer" 124 | }, 125 | { 126 | "command": "extension.fu-wrap-with-observer", 127 | "title": "Wrap with Mobx Observer" 128 | }, 129 | { 130 | "command": "extension.fu-wrap-with-builder", 131 | "title": "Wrap with Builder" 132 | }, 133 | { 134 | "command": "extension.fu-wrap-with-obx-getx", 135 | "title": "Wrap with Obx" 136 | }, 137 | { 138 | "command": "extension.fu-wrap-with-getx", 139 | "title": "Wrap with GetX" 140 | }, 141 | { 142 | "command": "extension.fu-wrap-with-layout-builder", 143 | "title": "Wrap with LayoutBuilder" 144 | }, 145 | { 146 | "command": "extension.fu-wrap-with-watch-signals", 147 | "title": "Wrap with Watch of Signals" 148 | }, 149 | { 150 | "command": "extension.getxfeature", 151 | "title": "GetX: New Feature" 152 | }, 153 | { 154 | "command": "extension.modularfeature", 155 | "title": "Flutter Modular: New Feature" 156 | }, 157 | { 158 | "command": "extension.modulariniital", 159 | "title": "Flutter Modular: Configure Framework" 160 | }, 161 | { 162 | "command": "extension.fvmInstallConfigure", 163 | "title": "FVM: Install and Configure Version" 164 | }, 165 | { 166 | "command": "extension.fvmConfigure", 167 | "title": "FVM: Configure Version" 168 | } 169 | ], 170 | "menus": { 171 | "explorer/context": [ 172 | { 173 | "when": "explorerResourceIsFolder", 174 | "command": "extension.generateClass", 175 | "group": "1_modification@1" 176 | }, 177 | { 178 | "when": "explorerResourceIsFolder", 179 | "command": "extension.generateSingletonClass", 180 | "group": "1_modification@1" 181 | }, 182 | { 183 | "when": "explorerResourceIsFolder", 184 | "command": "extension.generateStatelessWidget", 185 | "group": "1_modification@1" 186 | }, 187 | { 188 | "when": "explorerResourceIsFolder", 189 | "command": "extension.generateStatefulWidget", 190 | "group": "1_modification@1" 191 | }, 192 | { 193 | "when": "explorerResourceIsFolder", 194 | "command": "extension.generateInterface", 195 | "group": "1_modification@2" 196 | }, 197 | { 198 | "when": "explorerResourceIsFolder", 199 | "command": "extension.3-tiers", 200 | "group": "1_modification@3" 201 | }, 202 | { 203 | "when": "explorerResourceIsFolder", 204 | "command": "extension.mvc-feature", 205 | "group": "1_modification@3" 206 | }, 207 | { 208 | "when": "explorerResourceIsFolder", 209 | "command": "extension.clean-architecture-folders", 210 | "group": "1_modification@4" 211 | }, 212 | { 213 | "when": "explorerResourceIsFolder", 214 | "command": "extension.clean-architecture-folders-for-flutter", 215 | "group": "1_modification@5" 216 | }, 217 | { 218 | "when": "explorerResourceIsFolder", 219 | "command": "extension.generateTestFile", 220 | "group": "1_modification@6" 221 | }, 222 | { 223 | "when": "explorerResourceIsFolder", 224 | "command": "extension.getxfeature", 225 | "group": "1_modification@7" 226 | }, 227 | { 228 | "when": "explorerResourceIsFolder", 229 | "command": "extension.modularfeature", 230 | "group": "1_modification@7" 231 | }, 232 | { 233 | "when": "explorerResourceIsFolder", 234 | "command": "extension.modulariniital", 235 | "group": "1_modification@7" 236 | }, 237 | { 238 | "when": "explorerResourceIsFolder", 239 | "command": "extension.fvmConfigure", 240 | "group": "1_modification@8" 241 | }, 242 | { 243 | "when": "explorerResourceIsFolder", 244 | "command": "extension.fvmInstallConfigure", 245 | "group": "1_modification@8" 246 | } 247 | ], 248 | "commandPalette": [ 249 | { 250 | "command": "extension.fu-wrap-with-layout-builder", 251 | "when": "editorLangId == dart" 252 | }, 253 | { 254 | "command": "extension.fu-wrap-with-builder", 255 | "when": "editorLangId == dart" 256 | }, 257 | { 258 | "command": "extension.fu-wrap-with-value-notifier", 259 | "when": "editorLangId == dart" 260 | }, 261 | { 262 | "command": "extension.fu-wrap-with-consumer", 263 | "when": "editorLangId == dart" 264 | }, 265 | { 266 | "command": "extension.fu-wrap-with-observer", 267 | "when": "editorLangId == dart" 268 | } 269 | ] 270 | }, 271 | "snippets": [ 272 | { 273 | "language": "dart", 274 | "path": "./snippets/dart.json" 275 | }, 276 | { 277 | "language": "dart", 278 | "path": "./snippets/modular_old.json" 279 | }, 280 | { 281 | "language": "dart", 282 | "path": "./snippets/mobx.json" 283 | }, 284 | { 285 | "language": "dart", 286 | "path": "./snippets/modular.json" 287 | }, 288 | { 289 | "language": "dart", 290 | "path": "./snippets/cubit.json" 291 | }, 292 | { 293 | "language": "dart", 294 | "path": "./snippets/flutter_bloc.json" 295 | }, 296 | { 297 | "language": "dart", 298 | "path": "./snippets/aqueduct.json" 299 | }, 300 | { 301 | "language": "dart", 302 | "path": "./snippets/shelf.json" 303 | }, 304 | { 305 | "language": "dart", 306 | "path": "./snippets/flutter.json" 307 | }, 308 | { 309 | "language": "dart", 310 | "path": "./snippets/mockito.json" 311 | }, 312 | { 313 | "language": "dart", 314 | "path": "./snippets/provider.json" 315 | }, 316 | { 317 | "language": "dart", 318 | "path": "./snippets/getx.json" 319 | }, 320 | { 321 | "language": "dart", 322 | "path": "./snippets/dio.json" 323 | }, 324 | { 325 | "language": "dart", 326 | "path": "./snippets/json_serializable.json" 327 | } 328 | ] 329 | }, 330 | "scripts": { 331 | "lint": "eslint .", 332 | "pretest": "npm run lint", 333 | "test": "node ./test/runTest.js" 334 | }, 335 | "devDependencies": { 336 | "@types/glob": "^7.1.1", 337 | "@types/mocha": "^7.0.2", 338 | "@types/node": "^13.11.0", 339 | "@types/vscode": "^1.46.0", 340 | "eslint": "^6.8.0", 341 | "glob": "^7.1.6", 342 | "mocha": "^7.1.1", 343 | "typescript": "^3.9.10", 344 | "vscode-test": "^1.3.0" 345 | }, 346 | "dependencies": { 347 | "axios": "^1.4.0", 348 | "js-yaml": "^4.1.0", 349 | "lodash": "^4.17.19", 350 | "mkdirp": "^1.0.4", 351 | "semver": "^7.5.1" 352 | } 353 | } -------------------------------------------------------------------------------- /snippets/aqueduct.json: -------------------------------------------------------------------------------- 1 | { 2 | "aqueduct-create-operation": { 3 | "prefix": "fu-aqu-operation", 4 | "body": [ 5 | "@Operation.$1($2)", 6 | "Future $3($4) async {", 7 | " return Response.ok({});", 8 | "}" 9 | ] 10 | }, 11 | "aqueduct-create-serialization": { 12 | "prefix": "fu-aqu-serializable", 13 | "body": [ 14 | "import 'package:aqueduct/aqueduct.dart';", 15 | "", 16 | "class ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} extends Serializable {", 17 | " @override", 18 | " Map asMap() {", 19 | " return {};", 20 | " }", 21 | "", 22 | " @override", 23 | " void readFromMap(Map object) {", 24 | " ", 25 | " }", 26 | "}" 27 | ] 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /snippets/cubit.json: -------------------------------------------------------------------------------- 1 | { 2 | "cubit-onTransitional": { 3 | "prefix": "fu-cubitot", 4 | "body": [ 5 | "@override", 6 | "void onTransition(Transition transition) {", 7 | " $1", 8 | " super.onTransition(transition);", 9 | "}" 10 | ] 11 | }, 12 | "cubit-action": { 13 | "prefix": "fu-cubitaction", 14 | "body": [ 15 | "void $1($2){", 16 | "$3", 17 | "}" 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /snippets/dart.json: -------------------------------------------------------------------------------- 1 | { 2 | "freezed": { 3 | "prefix": "fu-freezed", 4 | "body": [ 5 | "import 'package:freezed_annotation/freezed_annotation.dart';", 6 | "", 7 | "part '$TM_FILENAME_BASE.freezed.dart';", 8 | "", 9 | "@freezed", 10 | "abstract class ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} with _$${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} {", 11 | " factory ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}}($2) = _${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}};", 12 | "}" 13 | ], 14 | "description": "Freezed snippet" 15 | }, 16 | "freezed_json_serializable": { 17 | "prefix": "fu-freezed-json-serializable", 18 | "body": [ 19 | "import 'package:freezed_annotation/freezed_annotation.dart';", 20 | "", 21 | "part '$TM_FILENAME_BASE.freezed.dart';", 22 | "part '$TM_FILENAME_BASE.g.dart';", 23 | "", 24 | "@freezed", 25 | "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} with _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 26 | " factory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}($1) = _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/};", 27 | " factory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}.fromJson(Map json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}FromJson(json);", 28 | "}" 29 | ], 30 | "description": "Freezed snippet with jsonSerializable" 31 | }, 32 | "interface": { 33 | "prefix": "fu-interface", 34 | "body": [ 35 | "abstract interface class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 36 | "$1", 37 | "}" 38 | ], 39 | "description": "Create abstract interface" 40 | }, 41 | "abstract class": { 42 | "prefix": "fu-abstract-class", 43 | "body": [ 44 | "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 45 | "$1", 46 | "}" 47 | ], 48 | "description": "Create abstract class" 49 | }, 50 | "class_interface_i_prefix": { 51 | "prefix": "fu-class-interface", 52 | "body": [ 53 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} implements I${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 54 | "$1", 55 | "}" 56 | ], 57 | "description": "Create class with interface only i prefix" 58 | }, 59 | "class_exception": { 60 | "prefix": "fu-class-exception", 61 | "body": [ 62 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} implements Exception {", 63 | "$1", 64 | "}" 65 | ], 66 | "description": "Create Exception Class " 67 | }, 68 | "constructor": { 69 | "prefix": "fu-constructor", 70 | "body": [ 71 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}($1);" 72 | ], 73 | "description": "Create constructor'" 74 | }, 75 | "private-constructor": { 76 | "prefix": "fu-private-constructor", 77 | "body": [ 78 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();" 79 | ], 80 | "description": "Create private constructor" 81 | }, 82 | "named-constructor": { 83 | "prefix": "fu-named-constructor", 84 | "body": [ 85 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}.$1($2);" 86 | ], 87 | "description": "Create named constructor" 88 | }, 89 | "dart_test_init": { 90 | "prefix": "fu-d-test-init", 91 | "body": [ 92 | "import 'package:test/test.dart';", 93 | "", 94 | "void main() {", 95 | "", 96 | " setUp((){});", 97 | "", 98 | " test('$1', () async {});", 99 | "", 100 | "}" 101 | ], 102 | "description": "Test Dart Init" 103 | }, 104 | "dart_callable_class": { 105 | "prefix": "fu-callable-class", 106 | "body": [ 107 | "", 108 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 109 | " $1 call($2) {}", 110 | "}" 111 | ], 112 | "description": "Create callable class" 113 | }, 114 | "dart_class_equatable": { 115 | "prefix": "fu-class-equatable", 116 | "body": [ 117 | "import 'package:equatable/equatable.dart';", 118 | "", 119 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends Equatable {", 120 | "$1", 121 | " @override", 122 | " List get props => [];", 123 | "}" 124 | ], 125 | "description": "create class with equatable" 126 | }, 127 | "dart_class": { 128 | "prefix": "fu-class", 129 | "body": [ 130 | "", 131 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 132 | " $1", 133 | "}" 134 | ], 135 | "description": "Create class" 136 | }, 137 | "dart_enum": { 138 | "prefix": "fu-enum", 139 | "body": [ 140 | "enum ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 141 | " $1", 142 | "}" 143 | ], 144 | "description": "Create enum" 145 | }, 146 | "dart_extension": { 147 | "prefix": "fu-extension", 148 | "body": [ 149 | "extension ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} on $1 {", 150 | " $2", 151 | "}" 152 | ], 153 | "description": "Create extension" 154 | }, 155 | "dart_mixin": { 156 | "prefix": "fu-mixin", 157 | "body": [ 158 | "", 159 | "mixin ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 160 | " $1", 161 | "}" 162 | ], 163 | "description": "Create mixin" 164 | }, 165 | "dart_class_singleton": { 166 | "prefix": "fu-class-singleton", 167 | "body": [ 168 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 169 | " static ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}? _instance;", 170 | " // Avoid self instance", 171 | " ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();", 172 | " static ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} get instance =>", 173 | " _instance ??= ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();", 174 | "}" 175 | ], 176 | "description": "Create a singleton class" 177 | }, 178 | "mysql_template": { 179 | "prefix": "fu-mysql-connection-template", 180 | "body": [ 181 | " MySqlConnection? conn;", 182 | " try {", 183 | " conn = await $1;", 184 | " await conn.query(''' ''', []);", 185 | "} on MySqlException catch (e, s) {", 186 | " throw $2();", 187 | "} finally {", 188 | " await conn?.close();", 189 | "}" 190 | ], 191 | "description": "Mysql connection template" 192 | }, 193 | "fu-test": { 194 | "prefix": "fu-test", 195 | "body": [ 196 | "test('$1', () async {", 197 | " //Arrange", 198 | " ", 199 | " //Act", 200 | " ", 201 | " //Assert", 202 | " ", 203 | "});" 204 | ], 205 | "description": "Test template" 206 | }, 207 | "fu-group-test": { 208 | "prefix": "fu-group-test", 209 | "body": [ 210 | "group('$1', () {", 211 | " test('$2', () async {", 212 | " //Arrange", 213 | " ", 214 | " //Act", 215 | " ", 216 | " //Assert", 217 | " ", 218 | " });", 219 | "});" 220 | ], 221 | "description": "Test template" 222 | }, 223 | "fu-static-attribute": { 224 | "prefix": "fu-static-attribute", 225 | "body": [ 226 | " static final $1 = $2;" 227 | ], 228 | "description": "create static atribute" 229 | }, 230 | "fu-zero-delay": { 231 | "prefix": "fu-zero-delay", 232 | "body": [ 233 | "await Future.delayed(Duration.zero);" 234 | ], 235 | "description": "Create Future.delayed zero" 236 | }, 237 | "fu-seconds-delay": { 238 | "prefix": "fu-seconds-delay", 239 | "body": [ 240 | "await Future.delayed(const Duration(seconds: $1));" 241 | ], 242 | "description": "Create Future.delayed in seconds" 243 | }, 244 | "fu-milliseconds-delay": { 245 | "prefix": "fu-milliseconds-delay", 246 | "body": [ 247 | "await Future.delayed(const Duration(milliseconds: $1));" 248 | ], 249 | "description": "Create Future.delayed in milliseconds'" 250 | } 251 | } -------------------------------------------------------------------------------- /snippets/dart/dart2.json: -------------------------------------------------------------------------------- 1 | { 2 | "freezed": { 3 | "prefix": "fu-freezed", 4 | "body": [ 5 | "import 'package:freezed_annotation/freezed_annotation.dart';", 6 | "", 7 | "part '$TM_FILENAME_BASE.freezed.dart';", 8 | "", 9 | "@freezed", 10 | "abstract class ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} with _$${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} {", 11 | " factory ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}}($2) = _${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}};", 12 | "}" 13 | ], 14 | "description": "Freezed snippet" 15 | }, 16 | "freezed_json_serializable": { 17 | "prefix": "fu-freezed-json-serializable", 18 | "body": [ 19 | "import 'package:freezed_annotation/freezed_annotation.dart';", 20 | "", 21 | "part '$TM_FILENAME_BASE.freezed.dart';", 22 | "part '$TM_FILENAME_BASE.g.dart';", 23 | "", 24 | "@freezed", 25 | "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} with _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 26 | " factory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}($1) = _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/};", 27 | " factory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}.fromJson(Map json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}FromJson(json);", 28 | "}" 29 | ], 30 | "description": "Freezed snippet with jsonSerializable" 31 | }, 32 | "interface": { 33 | "prefix": "fu-interface", 34 | "body": [ 35 | "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 36 | "$1", 37 | "}" 38 | ], 39 | "description": "Create abstract class 'interface'" 40 | }, 41 | "class_interface_i_prefix": { 42 | "prefix": "fu-class-interface", 43 | "body": [ 44 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} implements I${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 45 | "$1", 46 | "}" 47 | ], 48 | "description": "Create class with interface only i prefix" 49 | }, 50 | "class_exception": { 51 | "prefix": "fu-class-exception", 52 | "body": [ 53 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} implements Exception {", 54 | "$1", 55 | "}" 56 | ], 57 | "description": "Create class with interface only i prefix" 58 | }, 59 | "constructor": { 60 | "prefix": "fu-constructor", 61 | "body": [ 62 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}($1);" 63 | ], 64 | "description": "Create abstract class 'interface'" 65 | }, 66 | "private-constructor": { 67 | "prefix": "fu-private-constructor", 68 | "body": [ 69 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();" 70 | ], 71 | "description": "Create abstract class 'interface'" 72 | }, 73 | "named-constructor": { 74 | "prefix": "fu-named-constructor", 75 | "body": [ 76 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}.$1($2);" 77 | ], 78 | "description": "Create abstract class 'interface'" 79 | }, 80 | "dart_test_init": { 81 | "prefix": "fu-d-test-init", 82 | "body": [ 83 | "import 'package:test/test.dart';", 84 | "", 85 | "void main() {", 86 | "", 87 | " setUp((){});", 88 | "", 89 | " test('$1', () async {});", 90 | "", 91 | "}" 92 | ], 93 | "description": "Test Dart Init" 94 | }, 95 | "dart_callable_class": { 96 | "prefix": "fu-callable-class", 97 | "body": [ 98 | "", 99 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 100 | " $1 call($2) {}", 101 | "}" 102 | ], 103 | "description": "Create callable class" 104 | }, 105 | "dart_class_equatable": { 106 | "prefix": "fu-class-equatable", 107 | "body": [ 108 | "import 'package:equatable/equatable.dart';", 109 | "", 110 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends Equatable {", 111 | "$1", 112 | " @override", 113 | " List get props => [];", 114 | "}" 115 | ], 116 | "description": "create class with equatable" 117 | }, 118 | "dart_class": { 119 | "prefix": "fu-class", 120 | "body": [ 121 | "", 122 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 123 | " $1", 124 | "}" 125 | ], 126 | "description": "Create class" 127 | }, 128 | "dart_enum": { 129 | "prefix": "fu-enum", 130 | "body": [ 131 | "enum ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 132 | " $1", 133 | "}" 134 | ], 135 | "description": "Create enum" 136 | }, 137 | "dart_extension": { 138 | "prefix": "fu-extension", 139 | "body": [ 140 | "extension ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} on $1 {", 141 | " $2", 142 | "}" 143 | ], 144 | "description": "Create extension" 145 | }, 146 | "dart_mixin": { 147 | "prefix": "fu-mixin", 148 | "body": [ 149 | "", 150 | "mixin ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 151 | " $1", 152 | "}" 153 | ], 154 | "description": "Create mixin" 155 | }, 156 | "dart_class_singleton": { 157 | "prefix": "fu-class-singleton", 158 | "body": [ 159 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 160 | " static ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}? _instance;", 161 | " // Avoid self instance", 162 | " ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();", 163 | " static ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} get instance =>", 164 | " _instance ??= ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();", 165 | "}" 166 | ], 167 | "description": "Create a singleton class" 168 | }, 169 | "mysql_template": { 170 | "prefix": "fu-mysql-connection-template", 171 | "body": [ 172 | " MySqlConnection? conn;", 173 | " try {", 174 | " conn = await $1;", 175 | " await conn.query(''' ''', []);", 176 | "} on MySqlException catch (e, s) {", 177 | " throw $2();", 178 | "} finally {", 179 | " await conn?.close();", 180 | "}" 181 | ], 182 | "description": "Mysql connection template" 183 | }, 184 | "fu-test": { 185 | "prefix": "fu-test", 186 | "body": [ 187 | "test('$1', () async {", 188 | " //Arrange", 189 | " ", 190 | " //Act", 191 | " ", 192 | " //Assert", 193 | " ", 194 | "});" 195 | ], 196 | "description": "Test template" 197 | }, 198 | "fu-group-test": { 199 | "prefix": "fu-group-test", 200 | "body": [ 201 | "group('$1', () {", 202 | " test('$2', () async {", 203 | " //Arrange", 204 | " ", 205 | " //Act", 206 | " ", 207 | " //Assert", 208 | " ", 209 | " });", 210 | "});" 211 | ], 212 | "description": "Test template" 213 | }, 214 | "fu-static-attribute": { 215 | "prefix": "fu-static-attribute", 216 | "body": [ 217 | " static final $1 = $2;" 218 | ], 219 | "description": "create static atribute" 220 | }, 221 | "fu-zero-delay": { 222 | "prefix": "fu-zero-delay", 223 | "body": [ 224 | "await Future.delayed(Duration.zero);" 225 | ], 226 | "description": "Create Future.delayed zero" 227 | }, 228 | "fu-seconds-delay": { 229 | "prefix": "fu-seconds-delay", 230 | "body": [ 231 | "await Future.delayed(const Duration(seconds: $1));" 232 | ], 233 | "description": "Create Future.delayed in seconds" 234 | }, 235 | "fu-milliseconds-delay": { 236 | "prefix": "fu-milliseconds-delay", 237 | "body": [ 238 | "await Future.delayed(const Duration(milliseconds: $1));" 239 | ], 240 | "description": "Create Future.delayed in milliseconds'" 241 | } 242 | } -------------------------------------------------------------------------------- /snippets/dart/dart3.json: -------------------------------------------------------------------------------- 1 | { 2 | "freezed": { 3 | "prefix": "fu-freezed", 4 | "body": [ 5 | "import 'package:freezed_annotation/freezed_annotation.dart';", 6 | "", 7 | "part '$TM_FILENAME_BASE.freezed.dart';", 8 | "", 9 | "@freezed", 10 | "abstract class ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} with _$${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}} {", 11 | " factory ${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}}($2) = _${1:${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}};", 12 | "}" 13 | ], 14 | "description": "Freezed snippet" 15 | }, 16 | "freezed_json_serializable": { 17 | "prefix": "fu-freezed-json-serializable", 18 | "body": [ 19 | "import 'package:freezed_annotation/freezed_annotation.dart';", 20 | "", 21 | "part '$TM_FILENAME_BASE.freezed.dart';", 22 | "part '$TM_FILENAME_BASE.g.dart';", 23 | "", 24 | "@freezed", 25 | "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} with _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 26 | " factory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}($1) = _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/};", 27 | " factory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}.fromJson(Map json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}FromJson(json);", 28 | "}" 29 | ], 30 | "description": "Freezed snippet with jsonSerializable" 31 | }, 32 | "interface": { 33 | "prefix": "fu-interface", 34 | "body": [ 35 | "abstract interface class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 36 | "$1", 37 | "}" 38 | ], 39 | "description": "Create abstract interface" 40 | }, 41 | "abstract class": { 42 | "prefix": "fu-abstract-class", 43 | "body": [ 44 | "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 45 | "$1", 46 | "}" 47 | ], 48 | "description": "Create abstract class" 49 | }, 50 | "class_interface_i_prefix": { 51 | "prefix": "fu-class-interface", 52 | "body": [ 53 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} implements I${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 54 | "$1", 55 | "}" 56 | ], 57 | "description": "Create class with interface only i prefix" 58 | }, 59 | "class_exception": { 60 | "prefix": "fu-class-exception", 61 | "body": [ 62 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} implements Exception {", 63 | "$1", 64 | "}" 65 | ], 66 | "description": "Create Exception Class " 67 | }, 68 | "constructor": { 69 | "prefix": "fu-constructor", 70 | "body": [ 71 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}($1);" 72 | ], 73 | "description": "Create constructor'" 74 | }, 75 | "private-constructor": { 76 | "prefix": "fu-private-constructor", 77 | "body": [ 78 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();" 79 | ], 80 | "description": "Create private constructor" 81 | }, 82 | "named-constructor": { 83 | "prefix": "fu-named-constructor", 84 | "body": [ 85 | "${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}.$1($2);" 86 | ], 87 | "description": "Create named constructor" 88 | }, 89 | "dart_test_init": { 90 | "prefix": "fu-d-test-init", 91 | "body": [ 92 | "import 'package:test/test.dart';", 93 | "", 94 | "void main() {", 95 | "", 96 | " setUp((){});", 97 | "", 98 | " test('$1', () async {});", 99 | "", 100 | "}" 101 | ], 102 | "description": "Test Dart Init" 103 | }, 104 | "dart_callable_class": { 105 | "prefix": "fu-callable-class", 106 | "body": [ 107 | "", 108 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 109 | " $1 call($2) {}", 110 | "}" 111 | ], 112 | "description": "Create callable class" 113 | }, 114 | "dart_class_equatable": { 115 | "prefix": "fu-class-equatable", 116 | "body": [ 117 | "import 'package:equatable/equatable.dart';", 118 | "", 119 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends Equatable {", 120 | "$1", 121 | " @override", 122 | " List get props => [];", 123 | "}" 124 | ], 125 | "description": "create class with equatable" 126 | }, 127 | "dart_class": { 128 | "prefix": "fu-class", 129 | "body": [ 130 | "", 131 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 132 | " $1", 133 | "}" 134 | ], 135 | "description": "Create class" 136 | }, 137 | "dart_enum": { 138 | "prefix": "fu-enum", 139 | "body": [ 140 | "enum ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 141 | " $1", 142 | "}" 143 | ], 144 | "description": "Create enum" 145 | }, 146 | "dart_extension": { 147 | "prefix": "fu-extension", 148 | "body": [ 149 | "extension ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} on $1 {", 150 | " $2", 151 | "}" 152 | ], 153 | "description": "Create extension" 154 | }, 155 | "dart_mixin": { 156 | "prefix": "fu-mixin", 157 | "body": [ 158 | "", 159 | "mixin ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 160 | " $1", 161 | "}" 162 | ], 163 | "description": "Create mixin" 164 | }, 165 | "dart_class_singleton": { 166 | "prefix": "fu-class-singleton", 167 | "body": [ 168 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 169 | " static ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}? _instance;", 170 | " // Avoid self instance", 171 | " ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();", 172 | " static ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} get instance =>", 173 | " _instance ??= ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}._();", 174 | "}" 175 | ], 176 | "description": "Create a singleton class" 177 | }, 178 | "mysql_template": { 179 | "prefix": "fu-mysql-connection-template", 180 | "body": [ 181 | " MySqlConnection? conn;", 182 | " try {", 183 | " conn = await $1;", 184 | " await conn.query(''' ''', []);", 185 | "} on MySqlException catch (e, s) {", 186 | " throw $2();", 187 | "} finally {", 188 | " await conn?.close();", 189 | "}" 190 | ], 191 | "description": "Mysql connection template" 192 | }, 193 | "fu-test": { 194 | "prefix": "fu-test", 195 | "body": [ 196 | "test('$1', () async {", 197 | " //Arrange", 198 | " ", 199 | " //Act", 200 | " ", 201 | " //Assert", 202 | " ", 203 | "});" 204 | ], 205 | "description": "Test template" 206 | }, 207 | "fu-group-test": { 208 | "prefix": "fu-group-test", 209 | "body": [ 210 | "group('$1', () {", 211 | " test('$2', () async {", 212 | " //Arrange", 213 | " ", 214 | " //Act", 215 | " ", 216 | " //Assert", 217 | " ", 218 | " });", 219 | "});" 220 | ], 221 | "description": "Test template" 222 | }, 223 | "fu-static-attribute": { 224 | "prefix": "fu-static-attribute", 225 | "body": [ 226 | " static final $1 = $2;" 227 | ], 228 | "description": "create static atribute" 229 | }, 230 | "fu-zero-delay": { 231 | "prefix": "fu-zero-delay", 232 | "body": [ 233 | "await Future.delayed(Duration.zero);" 234 | ], 235 | "description": "Create Future.delayed zero" 236 | }, 237 | "fu-seconds-delay": { 238 | "prefix": "fu-seconds-delay", 239 | "body": [ 240 | "await Future.delayed(const Duration(seconds: $1));" 241 | ], 242 | "description": "Create Future.delayed in seconds" 243 | }, 244 | "fu-milliseconds-delay": { 245 | "prefix": "fu-milliseconds-delay", 246 | "body": [ 247 | "await Future.delayed(const Duration(milliseconds: $1));" 248 | ], 249 | "description": "Create Future.delayed in milliseconds'" 250 | } 251 | } -------------------------------------------------------------------------------- /snippets/dio.json: -------------------------------------------------------------------------------- 1 | { 2 | "dio_request": { 3 | "prefix": "fu-dio-template-request", 4 | "body": [ 5 | "try {", 6 | " final $1 = await $2.$3(", 7 | " '$4',", 8 | " );", 9 | "}", 10 | "on DioError catch (e, s) {", 11 | " log('$5', error: e, stackTrace: s);", 12 | " throw $6", 13 | "}" 14 | ], 15 | "description": "Dio template request" 16 | } 17 | } -------------------------------------------------------------------------------- /snippets/flutter.json: -------------------------------------------------------------------------------- 1 | { 2 | "statelessWidget": { 3 | "prefix": "fu-stl", 4 | "body": [ 5 | "import 'package:flutter/material.dart';", 6 | "", 7 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatelessWidget {", 8 | "", 9 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 10 | "", 11 | " @override", 12 | " Widget build(BuildContext context) {", 13 | " return Scaffold(", 14 | " appBar: AppBar(title: const Text('$1'),),", 15 | " body: Container(),", 16 | " );", 17 | " }", 18 | "}" 19 | ], 20 | "description": "Create Stateles Component with name of file and import material" 21 | }, 22 | "statefulWidget": { 23 | "prefix": "fu-stf", 24 | "body": [ 25 | "import 'package:flutter/material.dart';", 26 | "", 27 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatefulWidget {", 28 | "", 29 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 30 | "", 31 | " @override", 32 | " State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State();", 33 | "}", 34 | "", 35 | "class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> {", 36 | "", 37 | " @override", 38 | " Widget build(BuildContext context) {", 39 | " return Scaffold(", 40 | " appBar: AppBar(title: const Text('$1'),),", 41 | " body: Container(),", 42 | " );", 43 | " }", 44 | "}" 45 | ], 46 | "description": "Create Stateles Component with name of file and import material " 47 | }, 48 | "flutter_test_init": { 49 | "prefix": "fu-f-test-init", 50 | "body": [ 51 | "import 'package:flutter_test/flutter_test.dart';", 52 | "", 53 | "void main() {", 54 | "", 55 | " setUp((){});", 56 | "", 57 | " test('$1', () async {});", 58 | "", 59 | "}" 60 | ], 61 | "description": "Test Dart Init" 62 | }, 63 | "changeNotifier": { 64 | "prefix": "fu-change-notifier", 65 | "body": [ 66 | "import 'package:flutter/material.dart';", 67 | "", 68 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends ChangeNotifier {", 69 | " $1", 70 | "}" 71 | ], 72 | "description": "Create ChangeNotifier class" 73 | }, 74 | "valueNotifier": { 75 | "prefix": "fu-value-notifier", 76 | "body": [ 77 | "final $1 = ValueNotifier<$2>($3);" 78 | ], 79 | "description": "Create ValueNotifier" 80 | }, 81 | "textEditingController": { 82 | "prefix": "fu-text-editing-controller", 83 | "body": [ 84 | "final $1EC = TextEditingController($2);" 85 | ], 86 | "description": "Create TextEditingController" 87 | }, 88 | "global_form_key": { 89 | "prefix": "fu-form-key", 90 | "body": [ 91 | "final formKey = GlobalKey();" 92 | ], 93 | "description": "Create TextEditingController" 94 | }, 95 | "sized-box-spacer": { 96 | "prefix": "fu-separator", 97 | "body": [ 98 | "const SizedBox(", 99 | " height: $1,", 100 | ")," 101 | ], 102 | "description": "Create SizedBox separator" 103 | }, 104 | "part.g.dart": { 105 | "prefix": "fu-part", 106 | "body": "part '$TM_FILENAME_BASE.g.dart';" 107 | }, 108 | "fu-mediaquery": { 109 | "prefix": "fu-mediaquery", 110 | "body": "MediaQuery.of(context).$1" 111 | }, 112 | "fu-sw": { 113 | "prefix": "fu-sw", 114 | "body": "MediaQuery.of(context).size.width$1" 115 | }, 116 | "fu-sh": { 117 | "prefix": "fu-sh", 118 | "body": "MediaQuery.of(context).size.height$1" 119 | }, 120 | "fu-navigator": { 121 | "prefix": "fu-navigator", 122 | "body": "Navigator.of(context).$1" 123 | }, 124 | "fu-snackbar": { 125 | "prefix": "fu-snackbar", 126 | "body": "ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('$1')));" 127 | }, 128 | "fu-postframecallback": { 129 | "prefix": "fu-postframecallback", 130 | "body": [ 131 | "WidgetsBinding.instance.addPostFrameCallback((_) { ", 132 | " $1", 133 | "});" 134 | ] 135 | } 136 | 137 | 138 | } -------------------------------------------------------------------------------- /snippets/flutter/flutter2.17.json: -------------------------------------------------------------------------------- 1 | { 2 | "statelessWidget": { 3 | "prefix": "fu-stl", 4 | "body": [ 5 | "import 'package:flutter/material.dart';", 6 | "", 7 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatelessWidget {", 8 | "", 9 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 10 | "", 11 | " @override", 12 | " Widget build(BuildContext context) {", 13 | " return Scaffold(", 14 | " appBar: AppBar(title: const Text('$1'),),", 15 | " body: Container(),", 16 | " );", 17 | " }", 18 | "}" 19 | ], 20 | "description": "Create Stateles Component with name of file and import material" 21 | }, 22 | "statefulWidget": { 23 | "prefix": "fu-stf", 24 | "body": [ 25 | "import 'package:flutter/material.dart';", 26 | "", 27 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatefulWidget {", 28 | "", 29 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 30 | "", 31 | " @override", 32 | " State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State();", 33 | "}", 34 | "", 35 | "class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> {", 36 | "", 37 | " @override", 38 | " Widget build(BuildContext context) {", 39 | " return Scaffold(", 40 | " appBar: AppBar(title: const Text('$1'),),", 41 | " body: Container(),", 42 | " );", 43 | " }", 44 | "}" 45 | ], 46 | "description": "Create Stateles Component with name of file and import material " 47 | }, 48 | "flutter_test_init": { 49 | "prefix": "fu-f-test-init", 50 | "body": [ 51 | "import 'package:flutter_test/flutter_test.dart';", 52 | "", 53 | "void main() {", 54 | "", 55 | " setUp((){});", 56 | "", 57 | " test('$1', () async {});", 58 | "", 59 | "}" 60 | ], 61 | "description": "Test Dart Init" 62 | }, 63 | "changeNotifier": { 64 | "prefix": "fu-change-notifier", 65 | "body": [ 66 | "import 'package:flutter/material.dart';", 67 | "", 68 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends ChangeNotifier {", 69 | " $1", 70 | "}" 71 | ], 72 | "description": "Create ChangeNotifier class" 73 | }, 74 | "valueNotifier": { 75 | "prefix": "fu-value-notifier", 76 | "body": [ 77 | "final $1 = ValueNotifier<$2>($3);" 78 | ], 79 | "description": "Create ValueNotifier" 80 | }, 81 | "textEditingController": { 82 | "prefix": "fu-text-editing-controller", 83 | "body": [ 84 | "final $1EC = TextEditingController($2);" 85 | ], 86 | "description": "Create TextEditingController" 87 | }, 88 | "global_form_key": { 89 | "prefix": "fu-form-key", 90 | "body": [ 91 | "final formKey = GlobalKey();" 92 | ], 93 | "description": "Create TextEditingController" 94 | }, 95 | "sized-box-spacer": { 96 | "prefix": "fu-separator", 97 | "body": [ 98 | "const SizedBox(", 99 | " height: $1,", 100 | ")," 101 | ], 102 | "description": "Create SizedBox separator" 103 | }, 104 | "part.g.dart": { 105 | "prefix": "fu-part", 106 | "body": "part '$TM_FILENAME_BASE.g.dart';" 107 | }, 108 | "fu-mediaquery": { 109 | "prefix": "fu-mediaquery", 110 | "body": "MediaQuery.of(context).$1" 111 | }, 112 | "fu-sw": { 113 | "prefix": "fu-sw", 114 | "body": "MediaQuery.of(context).size.width$1" 115 | }, 116 | "fu-sh": { 117 | "prefix": "fu-sh", 118 | "body": "MediaQuery.of(context).size.height$1" 119 | }, 120 | "fu-navigator": { 121 | "prefix": "fu-navigator", 122 | "body": "Navigator.of(context).$1" 123 | }, 124 | "fu-snackbar": { 125 | "prefix": "fu-snackbar", 126 | "body": "ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('$1')));" 127 | }, 128 | "fu-postframecallback": { 129 | "prefix": "fu-postframecallback", 130 | "body": [ 131 | "WidgetsBinding.instance.addPostFrameCallback((_) { ", 132 | " $1", 133 | "});" 134 | ] 135 | } 136 | } -------------------------------------------------------------------------------- /snippets/flutter/flutter2.json: -------------------------------------------------------------------------------- 1 | { 2 | "statelessWidget": { 3 | "prefix": "fu-stl", 4 | "body": [ 5 | "import 'package:flutter/material.dart';", 6 | "", 7 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatelessWidget {", 8 | "", 9 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ Key? key }) : super(key: key);", 10 | "", 11 | " @override", 12 | " Widget build(BuildContext context) {", 13 | " return Scaffold(", 14 | " appBar: AppBar(title: const Text('$1'),),", 15 | " body: Container(),", 16 | " );", 17 | " }", 18 | "}" 19 | ], 20 | "description": "Create Stateles Component with name of file and import material" 21 | }, 22 | "statelessSuperWidget": { 23 | "prefix": "fu-stls", 24 | "body": [ 25 | "import 'package:flutter/material.dart';", 26 | "", 27 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatelessWidget {", 28 | "", 29 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 30 | "", 31 | " @override", 32 | " Widget build(BuildContext context) {", 33 | " return Scaffold(", 34 | " appBar: AppBar(title: const Text('$1'),),", 35 | " body: Container(),", 36 | " );", 37 | " }", 38 | "}" 39 | ], 40 | "description": "Create Stateles Component with name of file and import material" 41 | }, 42 | "statefulWidget": { 43 | "prefix": "fu-stf", 44 | "body": [ 45 | "import 'package:flutter/material.dart';", 46 | "", 47 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatefulWidget {", 48 | "", 49 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ Key? key }) : super(key: key);", 50 | "", 51 | " @override", 52 | " State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State();", 53 | "}", 54 | "", 55 | "class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> {", 56 | "", 57 | " @override", 58 | " Widget build(BuildContext context) {", 59 | " return Scaffold(", 60 | " appBar: AppBar(title: const Text('$1'),),", 61 | " body: Container(),", 62 | " );", 63 | " }", 64 | "}" 65 | ], 66 | "description": "Create Stateles Component with name of file and import material" 67 | }, 68 | 69 | "statefulSuperWidget": { 70 | "prefix": "fu-stfs", 71 | "body": [ 72 | "import 'package:flutter/material.dart';", 73 | "", 74 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatefulWidget {", 75 | "", 76 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 77 | "", 78 | " @override", 79 | " State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State();", 80 | "}", 81 | "", 82 | "class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> {", 83 | "", 84 | " @override", 85 | " Widget build(BuildContext context) {", 86 | " return Scaffold(", 87 | " appBar: AppBar(title: const Text('$1'),),", 88 | " body: Container(),", 89 | " );", 90 | " }", 91 | "}" 92 | ], 93 | "description": "Create Stateles Component with name of file and import material " 94 | }, 95 | "flutter_test_init": { 96 | "prefix": "fu-f-test-init", 97 | "body": [ 98 | "import 'package:flutter_test/flutter_test.dart';", 99 | "", 100 | "void main() {", 101 | "", 102 | " setUp((){});", 103 | "", 104 | " test('$1', () async {});", 105 | "", 106 | "}" 107 | ], 108 | "description": "Test Dart Init" 109 | }, 110 | "changeNotifier": { 111 | "prefix": "fu-change-notifier", 112 | "body": [ 113 | "import 'package:flutter/material.dart';", 114 | "", 115 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends ChangeNotifier {", 116 | " $1", 117 | "}" 118 | ], 119 | "description": "Create ChangeNotifier class" 120 | }, 121 | "valueNotifier": { 122 | "prefix": "fu-value-notifier", 123 | "body": [ 124 | "final $1 = ValueNotifier<$2>($3);" 125 | ], 126 | "description": "Create ValueNotifier" 127 | }, 128 | "textEditingController": { 129 | "prefix": "fu-text-editing-controller", 130 | "body": [ 131 | "final $1EC = TextEditingController($2);" 132 | ], 133 | "description": "Create TextEditingController" 134 | }, 135 | "global_form_key": { 136 | "prefix": "fu-form-key", 137 | "body": [ 138 | "final formKey = GlobalKey();" 139 | ], 140 | "description": "Create TextEditingController" 141 | }, 142 | "sized-box-spacer": { 143 | "prefix": "fu-separator", 144 | "body": [ 145 | "const SizedBox(", 146 | " height: $1,", 147 | ")," 148 | ], 149 | "description": "Create SizedBox separator" 150 | }, 151 | "part.g.dart": { 152 | "prefix": "fu-part", 153 | "body": "part '$TM_FILENAME_BASE.g.dart';" 154 | }, 155 | "fu-mediaquery": { 156 | "prefix": "fu-mediaquery", 157 | "body": "MediaQuery.of(context).$1" 158 | }, 159 | "fu-sw": { 160 | "prefix": "fu-sw", 161 | "body": "MediaQuery.of(context).size.width$1" 162 | }, 163 | "fu-sh": { 164 | "prefix": "fu-sh", 165 | "body": "MediaQuery.of(context).size.height$1" 166 | }, 167 | "fu-navigator": { 168 | "prefix": "fu-navigator", 169 | "body": "Navigator.of(context).$1" 170 | }, 171 | "fu-snackbar": { 172 | "prefix": "fu-snackbar", 173 | "body": "ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('$1')));" 174 | }, 175 | "fu-postframecallback": { 176 | "prefix": "fu-postframecallback", 177 | "body": [ 178 | "WidgetsBinding.instance.addPostFrameCallback((_) { ", 179 | " $1", 180 | "});" 181 | ] 182 | } 183 | 184 | 185 | } -------------------------------------------------------------------------------- /snippets/flutter/flutter3.10.json: -------------------------------------------------------------------------------- 1 | { 2 | "statelessWidget": { 3 | "prefix": "fu-stl", 4 | "body": [ 5 | "import 'package:flutter/material.dart';", 6 | "", 7 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatelessWidget {", 8 | "", 9 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 10 | "", 11 | " @override", 12 | " Widget build(BuildContext context) {", 13 | " return Scaffold(", 14 | " appBar: AppBar(title: const Text('$1'),),", 15 | " body: Container(),", 16 | " );", 17 | " }", 18 | "}" 19 | ], 20 | "description": "Create Stateles Component with name of file and import material" 21 | }, 22 | "statefulWidget": { 23 | "prefix": "fu-stf", 24 | "body": [ 25 | "import 'package:flutter/material.dart';", 26 | "", 27 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatefulWidget {", 28 | "", 29 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({ super.key });", 30 | "", 31 | " @override", 32 | " State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State();", 33 | "}", 34 | "", 35 | "class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> {", 36 | "", 37 | " @override", 38 | " Widget build(BuildContext context) {", 39 | " return Scaffold(", 40 | " appBar: AppBar(title: const Text('$1'),),", 41 | " body: Container(),", 42 | " );", 43 | " }", 44 | "}" 45 | ], 46 | "description": "Create Stateles Component with name of file and import material " 47 | }, 48 | "flutter_test_init": { 49 | "prefix": "fu-f-test-init", 50 | "body": [ 51 | "import 'package:flutter_test/flutter_test.dart';", 52 | "", 53 | "void main() {", 54 | "", 55 | " setUp((){});", 56 | "", 57 | " test('$1', () async {});", 58 | "", 59 | "}" 60 | ], 61 | "description": "Test Dart Init" 62 | }, 63 | "changeNotifier": { 64 | "prefix": "fu-change-notifier", 65 | "body": [ 66 | "import 'package:flutter/material.dart';", 67 | "", 68 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends ChangeNotifier {", 69 | " $1", 70 | "}" 71 | ], 72 | "description": "Create ChangeNotifier class" 73 | }, 74 | "valueNotifier": { 75 | "prefix": "fu-value-notifier", 76 | "body": [ 77 | "final $1 = ValueNotifier<$2>($3);" 78 | ], 79 | "description": "Create ValueNotifier" 80 | }, 81 | "textEditingController": { 82 | "prefix": "fu-text-editing-controller", 83 | "body": [ 84 | "final $1EC = TextEditingController($2);" 85 | ], 86 | "description": "Create TextEditingController" 87 | }, 88 | "global_form_key": { 89 | "prefix": "fu-form-key", 90 | "body": [ 91 | "final formKey = GlobalKey();" 92 | ], 93 | "description": "Create TextEditingController" 94 | }, 95 | "sized-box-spacer": { 96 | "prefix": "fu-separator", 97 | "body": [ 98 | "const SizedBox(", 99 | " height: $1,", 100 | ")," 101 | ], 102 | "description": "Create SizedBox separator" 103 | }, 104 | "part.g.dart": { 105 | "prefix": "fu-part", 106 | "body": "part '$TM_FILENAME_BASE.g.dart';" 107 | }, 108 | "fu-mediaquery": { 109 | "prefix": "fu-mediaquery", 110 | "body": "MediaQuery.of(context).$1" 111 | }, 112 | "fu-sw": { 113 | "prefix": "fu-sw", 114 | "body": "MediaQuery.of(context).size.width$1" 115 | }, 116 | "fu-sh": { 117 | "prefix": "fu-sh", 118 | "body": "MediaQuery.of(context).size.height$1" 119 | }, 120 | "fu-navigator": { 121 | "prefix": "fu-navigator", 122 | "body": "Navigator.of(context).$1" 123 | }, 124 | "fu-snackbar": { 125 | "prefix": "fu-snackbar", 126 | "body": "ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('$1')));" 127 | }, 128 | "fu-postframecallback": { 129 | "prefix": "fu-postframecallback", 130 | "body": [ 131 | "WidgetsBinding.instance.addPostFrameCallback((_) { ", 132 | " $1", 133 | "});" 134 | ] 135 | } 136 | 137 | 138 | } -------------------------------------------------------------------------------- /snippets/flutter_bloc.json: -------------------------------------------------------------------------------- 1 | { 2 | "flutter_bloc-transformEvents": { 3 | "prefix": "fu-bloctransform", 4 | "body": [ 5 | "@override", 6 | " Stream> transformEvents(events, transitionFn) {", 7 | " $1", 8 | " return super.transformEvents(events, transitionFn);", 9 | "}" 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /snippets/getx.json: -------------------------------------------------------------------------------- 1 | { 2 | "getxbindings": { 3 | "prefix": "fu-getxbinding", 4 | "body": [ 5 | "import 'package:get/get.dart';", 6 | "", 7 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} implements Bindings {", 8 | " @override", 9 | " void dependencies() {", 10 | " $1", 11 | " }", 12 | "}" 13 | ], 14 | "description": "Create GetX Binding" 15 | }, 16 | "getxcontroller": { 17 | "prefix": "fu-getxcontroller", 18 | "body": [ 19 | "import 'package:get/get.dart';", 20 | "", 21 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends GetxController { ", 22 | "$1", 23 | "}" 24 | ], 25 | "description": "Create GetX Controller" 26 | }, 27 | "getxRx": { 28 | "prefix": "fu-getxrx", 29 | "body": [ 30 | "final $1 = Rx<$2>($3);" 31 | ], 32 | "description": "Create GetX Rx" 33 | }, 34 | "getxRxn": { 35 | "prefix": "fu-getxrxn", 36 | "body": [ 37 | "final $1 = Rxn<$2>();" 38 | ], 39 | "description": "Create GetX Rxn" 40 | }, 41 | "getxObs": { 42 | "prefix": "fu-getxobs", 43 | "body": [ 44 | "final $1 = $2.obs;" 45 | ], 46 | "description": "Create GetX Rx with .obs" 47 | }, 48 | "getxcontrollerOnInit": { 49 | "prefix": "fu-getxoninit", 50 | "body": [ 51 | "@override", 52 | "void onInit() {", 53 | "super.onInit();", 54 | "$1", 55 | "}" 56 | ], 57 | "description": "GetX lifeCycle onInit" 58 | }, 59 | "getxcontrollerOnClose": { 60 | "prefix": "fu-getxonclose", 61 | "body": [ 62 | "@override", 63 | "void onClose() {", 64 | "super.onClose();", 65 | "$1", 66 | "}" 67 | ], 68 | "description": "GetX lifeCycle onClose" 69 | }, 70 | "getxpage": { 71 | "prefix": "fu-getxpage", 72 | "body": [ 73 | "import 'package:flutter/material.dart';", 74 | "import 'package:get/get.dart';", 75 | "", 76 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends GetView<$2Controller> {", 77 | " ", 78 | " const ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}({Key? key}) : super(key: key);", 79 | " ", 80 | " @override", 81 | " Widget build(BuildContext context) {", 82 | " return Scaffold(", 83 | " appBar: AppBar(title: const Text('${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}'),),", 84 | " body: Container(),", 85 | " );", 86 | " }", 87 | "}" 88 | ], 89 | "description": "Create Page with GetView" 90 | } 91 | } -------------------------------------------------------------------------------- /snippets/json_serializable.json: -------------------------------------------------------------------------------- 1 | { 2 | "fu-class-json-serializable": { 3 | "prefix": "fu-class-json-serializable", 4 | "body": [ 5 | "import 'package:json_annotation/json_annotation.dart';", 6 | "", 7 | "part '$TM_FILENAME_BASE.g.dart';", 8 | "", 9 | "@JsonSerializable()", 10 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 11 | "", 12 | " factory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}.fromJson(Map json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}FromJson(json);", 13 | "", 14 | " Map toJson() => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}ToJson(this);", 15 | "}" 16 | ], 17 | "description": "Create class with json_serializable" 18 | } 19 | } -------------------------------------------------------------------------------- /snippets/mobx.json: -------------------------------------------------------------------------------- 1 | { 2 | "mobx-store": { 3 | "prefix": "fu-mobx-store", 4 | "body": [ 5 | "import 'package:mobx/mobx.dart';", 6 | "part '${TM_FILENAME_BASE}.g.dart';", 7 | "", 8 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} = ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}Base with _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/};", 9 | "", 10 | "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}Base with Store {", 11 | "", 12 | "}" 13 | ] 14 | } 15 | } -------------------------------------------------------------------------------- /snippets/mockito.json: -------------------------------------------------------------------------------- 1 | { 2 | "test_init_when_async": { 3 | "prefix": "fu-test-when-async", 4 | "body": [ 5 | "when($1).thenAnswer((_) async => $2);" 6 | ], 7 | "description": "Add when mockito async" 8 | }, 9 | "test_init_when": { 10 | "prefix": "fu-test-when", 11 | "body": [ 12 | "when($1).thenReturn($2);" 13 | ], 14 | "description": "Test add when mockito" 15 | }, 16 | "test_init_when_throw": { 17 | "prefix": "fu-test-when-throw", 18 | "body": [ 19 | "when($1).thenThrow($2);" 20 | ], 21 | "description": "Test add when mockito" 22 | }, 23 | "test_mock": { 24 | "prefix": "fu-test-mock", 25 | "body": [ 26 | "class $1 extends Mock implements $2 {}" 27 | ], 28 | "description": "Create mock class" 29 | } 30 | } -------------------------------------------------------------------------------- /snippets/modular.json: -------------------------------------------------------------------------------- 1 | { 2 | "modular-initial-config": { 3 | "prefix": "fu-modular-initial-config", 4 | "body": [ 5 | "import 'package:flutter/material.dart';", 6 | "import 'package:flutter_modular/flutter_modular.dart';", 7 | "", 8 | "void main(){", 9 | " return runApp(ModularApp(module: AppModule(), child: AppWidget()));", 10 | "}" 11 | ] 12 | }, 13 | "modular-app-widget": { 14 | "prefix": "fu-modular-app-widget", 15 | "body": [ 16 | "import 'package:flutter/material.dart';", 17 | "import 'package:flutter_modular/flutter_modular.dart';", 18 | 19 | "", 20 | "class AppWidget extends StatelessWidget {", 21 | " Widget build(BuildContext context){", 22 | " return MaterialApp.router(", 23 | " title: '$1',", 24 | " theme: ThemeData(primarySwatch: Colors.blue),", 25 | " routeInformationParser: Modular.routeInformationParser,", 26 | " routerDelegate: Modular.routerDelegate,", 27 | " );", 28 | " }", 29 | "}" 30 | ] 31 | }, 32 | "modular-child-router": { 33 | "prefix": "fu-modular-router-child", 34 | "body": [ 35 | "ChildRoute($1, child: (_, args) => $2)," 36 | ] 37 | }, 38 | "modular-router": { 39 | "prefix": "fu-modular-router", 40 | "body": [ 41 | "ModuleRoute($1, module: $2)," 42 | ] 43 | }, 44 | "modular-WildcardRoute": { 45 | "prefix": "fu-modular-wildcard-route", 46 | "body": [ 47 | "WildcardRoute($1, child: (_, args) => $2)," 48 | ] 49 | }, 50 | "modular-inital-page-router": { 51 | "prefix": "fu-modular-initial-router-child", 52 | "body": [ 53 | "ChildRoute(Modular.initialRoute, child: (context, args) => $2)" 54 | ] 55 | }, 56 | "modular-bind-factory": { 57 | "prefix": "fu-modular-bind-factory", 58 | "body": [ 59 | "Bind.factory((i) => $1)," 60 | ] 61 | }, 62 | "modular-bind-instance": { 63 | "prefix": "fu-modular-bind-instance", 64 | "body": [ 65 | "Bind.instance($1)," 66 | ] 67 | }, 68 | "modular-bind-singleton": { 69 | "prefix": "fu-modular-bind-singleton", 70 | "body": [ 71 | "Bind.singleton((i) => $1)," 72 | ] 73 | }, 74 | "modular-bind-lazySingleton": { 75 | "prefix": "fu-modular-bind-lazySingleton", 76 | "body": [ 77 | "Bind.lazySingleton((i) => $1)," 78 | ] 79 | }, 80 | "modular-bind-lazySingleton-interface": { 81 | "prefix": "fu-modular-bind-lazySingleton-interface", 82 | "body": [ 83 | "Bind.lazySingleton<$1>((i) => $2)," 84 | ] 85 | }, 86 | "modular-bind-lazySingleton-interface-cleancode": { 87 | "prefix": "fu-modular-bind-lazySingleton-cc", 88 | "body": [ 89 | "Bind.lazySingleton<$1>((i) => $1Impl($2))," 90 | ], 91 | "description": "Bind.lazySingleton with interface and clean code pattern" 92 | }, 93 | "modular-bind-factory-interface": { 94 | "prefix": "fu-modular-bind-factory-interface", 95 | "body": [ 96 | "Bind.factory<$1>((i) => $2)," 97 | ] 98 | }, 99 | "modular-bind-factory-interface-cleancode": { 100 | "prefix": "fu-modular-bind-factory-cc", 101 | "body": [ 102 | "Bind.factory<$1>((i) => $1Impl($2))," 103 | ], 104 | "description": "Bind.factory with interface and clean code pattern" 105 | }, 106 | "modular-bind-instance-interface": { 107 | "prefix": "fu-modular-bind-instance-interface", 108 | "body": [ 109 | "Bind.instance<$1>($2)," 110 | ] 111 | }, 112 | "modular-bind-instance-interface-cleancode": { 113 | "prefix": "fu-modular-bind-instance-cc", 114 | "body": [ 115 | "Bind.instance<$1>((i) => $1Impl($2))," 116 | ], 117 | "description": "Bind.instance with interface and clean code pattern" 118 | }, 119 | "modular-bind-singleton-interface": { 120 | "prefix": "fu-modular-bind-singleton-interface", 121 | "body": [ 122 | "Bind.singleton<$1>((i) => $2)," 123 | ] 124 | }, 125 | "modular-generate-mdule": { 126 | "prefix": "fu-modular-module", 127 | "body": [ 128 | "import 'package:flutter_modular/flutter_modular.dart';", 129 | "", 130 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends Module {", 131 | "", 132 | " @override", 133 | " List get binds => [];", 134 | "", 135 | " @override", 136 | " List get routes => [", 137 | " ChildRoute('/', child: (context, args) => $1)", 138 | " ];", 139 | "", 140 | "}" 141 | ] 142 | } 143 | } -------------------------------------------------------------------------------- /snippets/modular_old.json: -------------------------------------------------------------------------------- 1 | { 2 | "modular-child-router": { 3 | "prefix": "fu-modular-old-router-child", 4 | "body": [ 5 | "ModularRouter($1, child: (context, args) => $2)" 6 | ] 7 | }, 8 | "modular-router": { 9 | "prefix": "fu-modular-old-router", 10 | "body": [ 11 | "ModularRouter($1, module: $2)," 12 | ] 13 | }, 14 | "modular-inital-router": { 15 | "prefix": "fu-modular-old-initial-router-module", 16 | "body": [ 17 | "ModularRouter(Modular.initialRoute, module: $2)," 18 | ] 19 | }, 20 | "modular-inital-page-router": { 21 | "prefix": "fu-modular-old-initial-router-child", 22 | "body": [ 23 | "ModularRouter(Modular.initialRoute, child: (context, args) => $2)" 24 | ] 25 | }, 26 | "modular-bind": { 27 | "prefix": "fu-modular-old-bind", 28 | "body": [ 29 | "Bind((i) => $1($2))," 30 | ] 31 | }, 32 | "modular-codegen-inject": { 33 | "prefix": "fu-modular-old_codegen_inject", 34 | "body": [ 35 | "part '${TM_FILENAME_BASE}.g.dart';", 36 | "", 37 | "@Injectable($1)" 38 | ] 39 | }, 40 | "modular-generate-mdule": { 41 | "prefix": "fu-modular-old-module", 42 | "body": [ 43 | "import 'package:flutter_modular/flutter_modular.dart';", 44 | "", 45 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends ChildModule {", 46 | "", 47 | " @override", 48 | " List get binds => [];", 49 | "", 50 | " @override", 51 | " List get routers => [$1];", 52 | "", 53 | " static Inject get to => Inject<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}>.of();", 54 | "}" 55 | ] 56 | } 57 | 58 | 59 | } -------------------------------------------------------------------------------- /snippets/provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "provider-read": { 3 | "prefix": "fu-provider-read", 4 | "body": [ 5 | "context.read<$1>();" 6 | ] 7 | }, 8 | "provider-watch": { 9 | "prefix": "fu-provider-watch", 10 | "body": [ 11 | "context.watch<$1>();" 12 | ] 13 | }, 14 | "provider-select": { 15 | "prefix": "fu-provider-select", 16 | "body": [ 17 | "context.select<$1, ?2>((value) {});" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /snippets/shelf.json: -------------------------------------------------------------------------------- 1 | { 2 | "shelf-controller": { 3 | "prefix": "fu-shelf-controller", 4 | "body": [ 5 | "import 'dart:async';", 6 | "import 'dart:convert';", 7 | "import 'package:shelf/shelf.dart';", 8 | "import 'package:shelf_router/shelf_router.dart';", 9 | "", 10 | "part '${TM_FILENAME_BASE}.g.dart';", 11 | "", 12 | "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} {", 13 | "", 14 | " @Route.get('/')", 15 | " Future find(Request request) async { ", 16 | " $1return Response.ok(jsonEncode(''));", 17 | " }", 18 | "", 19 | " Router get router => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}Router(this);", 20 | "}" 21 | ], 22 | "description": "Create controller shelf" 23 | }, 24 | "shelf-operation": { 25 | "prefix": "fu-shelf-operation", 26 | "body": [ 27 | "@Route.$1('$2')", 28 | "Future $3(Request request) async{", 29 | " return Response.ok(jsonEncode(''));", 30 | "}" 31 | ], 32 | "description": "Create shelf operation" 33 | } 34 | } -------------------------------------------------------------------------------- /src/commands/clean_arch_folders.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const _ = require('lodash'); 5 | // const { wrapWithProviderConsumerBuilder, wrapWithValueListenableBuilder, wrapWithMobXObserverBuilder } = require('../commands/wrap-with'); 6 | const { createFile } = require('../commands/create_file'); 7 | const path = require('path'); 8 | 9 | async function createCleanArchFolders(uri) { 10 | const featureName = await promptForFeatureName("Feature Clean Architecture Name"); 11 | if (featureName) { 12 | mkdirp(path.join(uri.fsPath, featureName)) 13 | const baseUrl = path.join(uri.fsPath, featureName); 14 | mkdirp(path.join(baseUrl, '/data')) 15 | .then(() => { 16 | mkdirp(path.join(baseUrl, '/data/datasource')) 17 | mkdirp(path.join(baseUrl, '/data/drivers')) 18 | }) 19 | .catch((err) => console.log(err)); 20 | mkdirp(path.join(baseUrl, '/infra')).then(() => { 21 | mkdirp(path.join(baseUrl, '/infra/repository')) 22 | mkdirp(path.join(baseUrl, '/infra/datasources')) 23 | mkdirp(path.join(baseUrl, '/infra/models')) 24 | }) 25 | 26 | mkdirp(path.join(baseUrl, '/domain')) 27 | .then(() => { 28 | mkdirp(path.join(baseUrl, '/domain/entities')) 29 | mkdirp(path.join(baseUrl, '/domain/repositories')) 30 | mkdirp(path.join(baseUrl, '/domain/usecases')) 31 | }) 32 | .catch((err) => console.log(err)); 33 | 34 | mkdirp(path.join(baseUrl, '/presenter')) 35 | .then(() => { 36 | mkdirp(path.join(baseUrl, '/presenter/controllers')) 37 | mkdirp(path.join(baseUrl, '/presenter/models')) 38 | mkdirp(path.join(baseUrl, '/presenter/usecases')) 39 | }) 40 | .catch((err) => console.log(err)); 41 | } 42 | } 43 | 44 | function promptForFeatureName(prompt) { 45 | const FeatureNamePromptOptions = { 46 | prompt: prompt, 47 | placeHolder: "Feature Name" 48 | }; 49 | return vscode.window.showInputBox(FeatureNamePromptOptions); 50 | } 51 | 52 | module.exports = { createCleanArchFolders }; -------------------------------------------------------------------------------- /src/commands/clean_arch_folders_for_flutter.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const _ = require('lodash'); 5 | // const { wrapWithProviderConsumerBuilder, wrapWithValueListenableBuilder, wrapWithMobXObserverBuilder } = require('../commands/wrap-with'); 6 | const { createFile } = require('./create_file'); 7 | const path = require('path'); 8 | 9 | async function createCleanArchFoldersForFlutter(uri) { 10 | const featureName = await promptForFeatureName("Feature Clean Architecture Name"); 11 | if (featureName) { 12 | mkdirp(path.join(uri.fsPath , featureName)) 13 | const baseUrl = path.join(uri.fsPath , featureName); 14 | mkdirp(path.join(baseUrl, '/data')) 15 | .then(() => { 16 | mkdirp(path.join(baseUrl, '/data/datasource')) 17 | }) 18 | .catch((err) => console.log(err)); 19 | 20 | mkdirp(path.join(baseUrl, '/infra')).then(() => { 21 | mkdirp(path.join(baseUrl, '/infra/repository')) 22 | mkdirp(path.join(baseUrl, '/infra/datasources')) 23 | mkdirp(path.join(baseUrl, '/infra/models')) 24 | }) 25 | 26 | mkdirp(path.join(baseUrl, '/domain')) 27 | .then(() => { 28 | mkdirp(path.join(baseUrl, '/domain/entities')) 29 | mkdirp(path.join(baseUrl, '/domain/infra')) 30 | mkdirp(path.join(baseUrl, '/domain/usecases')) 31 | }) 32 | .catch((err) => console.log(err)); 33 | 34 | mkdirp(path.join(baseUrl, '/ui')) 35 | .catch((err) => console.log(err)); 36 | 37 | mkdirp(path.join(baseUrl, '/presenter')) 38 | .then(() => { 39 | mkdirp(path.join(baseUrl, '/presenter/controllers')) 40 | mkdirp(path.join(baseUrl, '/presenter/usecases')) 41 | }) 42 | .catch((err) => console.log(err)); 43 | } 44 | 45 | } 46 | 47 | function promptForFeatureName(prompt) { 48 | const FeatureNamePromptOptions = { 49 | prompt: prompt, 50 | placeHolder: "Feature Name" 51 | }; 52 | return vscode.window.showInputBox(FeatureNamePromptOptions); 53 | } 54 | 55 | module.exports = {createCleanArchFoldersForFlutter}; -------------------------------------------------------------------------------- /src/commands/create_file.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | 3 | async function createFile(fileName) { 4 | let wsedit = new vscode.WorkspaceEdit(); 5 | const filePath = vscode.Uri.file(fileName); 6 | wsedit.createFile(filePath); 7 | await vscode.workspace.applyEdit(wsedit); 8 | } 9 | 10 | module.exports = {createFile} -------------------------------------------------------------------------------- /src/commands/create_getter.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | 5 | async function createGetter(uri) { 6 | const editor = vscode.window.activeTextEditor; 7 | 8 | if (editor) { 9 | const document = editor.document; 10 | const position = editor.selection.active; 11 | 12 | // Expressão regular para extrair tipo e nome do atributo 13 | const lineText = editor.document.lineAt(position.line); 14 | 15 | if (lineText) { 16 | const text = lineText.text; 17 | const match = /(.*?)(?:\s*=|\s*;)/.exec(text.trim()); 18 | 19 | if (match) { 20 | var str = match[0]; 21 | 22 | // var data = str.split(" "); 23 | // const type = data[0]; 24 | // const name = data[1]; 25 | // var getterCode = `\n${type} get ${name.replace(/^_/, "")} => ${name};\n`; 26 | var getterCode = ''; 27 | if(str.startsWith('final') || str.startsWith('var')){ 28 | 29 | if(str.startsWith('final') || str.startsWith('var')){ 30 | str = str.replace('final', ''); 31 | str = str.replace('var', ''); 32 | str = str.trim(); 33 | } 34 | var data = str.split(" "); 35 | var type = data[0]; 36 | var name = data[1].replace('\;', ''); 37 | 38 | if(name == '=') { 39 | name = type; 40 | type = await vscode.window.showInputBox({prompt: "unidentified type, please enter the type" }); 41 | 42 | } 43 | getterCode = `\n${type} get ${name.replace(/^_/, "")} => ${name};\n`; 44 | }else if(str.endsWith(";")) { 45 | var data = str.split(" "); 46 | if(data.length <2){ 47 | vscode.window.showErrorMessage('invalid attribute'); 48 | return; 49 | 50 | } 51 | const type = data[0]; 52 | const name = data[1].replace('\;', ''); 53 | getterCode = `\n${type} get ${name.replace(/^_/, "")} => ${name};\n`; 54 | }else{ 55 | var data = str.split(" "); 56 | const type = data[0]; 57 | const name = data[1].replace('\;', ''); 58 | getterCode = `\n${type} get ${name.replace(/^_/, "")} => ${name};\n`; 59 | } 60 | 61 | // const type = match[0]; 62 | // const name = match[1]; 63 | // const getterCode = `\n${type} get ${name.replace(/^_/, "")} => ${name};\n`; 64 | 65 | await editor.edit(editBuilder => { 66 | editBuilder.insert(lineText.range.end, getterCode); 67 | }); 68 | await vscode.commands.executeCommand('editor.action.formatDocument'); 69 | } 70 | } 71 | } 72 | } 73 | 74 | 75 | 76 | module.exports = { createGetter }; -------------------------------------------------------------------------------- /src/commands/fvm_configure.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const { getContentTemplate } = require('./templates/read_file_template'); 5 | 6 | async function fvmConfigure(uri) { 7 | const rootPath = vscode.workspace.workspaceFolders[0].uri.fsPath; 8 | const folder = path.join(rootPath, '.vscode'); 9 | if (!fs.existsSync(folder)) { 10 | fs.mkdirSync(folder) 11 | } 12 | const templateSettings = getContentTemplate(path.join('fvm', 'settings.template')); 13 | fs.writeFileSync(path.join(folder, 'settings.json'), templateSettings, 'utf-8'); 14 | fs.appendFileSync(path.join(rootPath, ".gitignore"), '\n\n.fvm/') 15 | 16 | const options = ["Yes", "No"]; 17 | 18 | vscode.window.showInformationMessage("Would you like to run fvm install?", ...options).then(async selection => { 19 | if (selection === "Yes") { 20 | const terminal = vscode.window.createTerminal(`FVM Terminal`); 21 | terminal.show(true); 22 | 23 | // Executa um comando no terminal 24 | terminal.sendText("fvm install"); 25 | vscode.window.showInformationMessage('FVM config successfully') 26 | } 27 | }); 28 | 29 | } 30 | module.exports = { fvmConfigure }; -------------------------------------------------------------------------------- /src/commands/fvm_install_configure.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const { getContentTemplate } = require('./templates/read_file_template'); 5 | 6 | async function fvmInstallConfigure(uri) { 7 | const fvmVersion = await promptForFeatureName('What version of flutter would you like?') 8 | if (fvmVersion !== '') { 9 | 10 | const task = new vscode.Task( 11 | { type: 'shell' }, 12 | vscode.TaskScope.Workspace, 13 | `Installing Version ${fvmVersion}`, 14 | `fvm install ${fvmVersion}`, 15 | new vscode.ShellExecution(`fvm install ${fvmVersion}`) 16 | ); 17 | 18 | const installTask = await vscode.tasks.executeTask(task); 19 | let useTask; 20 | vscode.tasks.onDidEndTask(async event => { 21 | 22 | if (event.execution === installTask) { 23 | const taskUse = new vscode.Task( 24 | { type: 'shell' }, 25 | vscode.TaskScope.Workspace, 26 | `Configure Version ${fvmVersion}`, 27 | `fvm use ${fvmVersion}`, 28 | new vscode.ShellExecution(`fvm use ${fvmVersion}`) 29 | ); 30 | useTask = await vscode.tasks.executeTask(taskUse); 31 | 32 | } else if (event.execution === useTask) { 33 | const rootPath = vscode.workspace.workspaceFolders[0].uri.fsPath 34 | const folder = path.join(rootPath, '.vscode'); 35 | if (!fs.existsSync(folder)) { 36 | fs.mkdirSync(folder) 37 | } 38 | const templateSettings = getContentTemplate(path.join('fvm', 'settings.template')); 39 | fs.writeFileSync(path.join(folder, 'settings.json'), templateSettings, 'utf-8'); 40 | fs.appendFileSync(path.join(rootPath, ".gitignore"), '\n\n.fvm') 41 | } 42 | }); 43 | 44 | 45 | 46 | } 47 | 48 | } 49 | 50 | function promptForFeatureName(prompt, placeHolder = 'Ex: 3.0.0') { 51 | const FeatureNamePromptOptions = { 52 | prompt: prompt, 53 | placeHolder: placeHolder 54 | }; 55 | return vscode.window.showInputBox(FeatureNamePromptOptions); 56 | } 57 | 58 | module.exports = { fvmInstallConfigure }; -------------------------------------------------------------------------------- /src/commands/generate_class.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | 5 | async function generateClass(uri) { 6 | const className = await promptForFeatureName("Class Name"); 7 | if(!className){ 8 | vscode.window.showInformationMessage('Creating a Dart Class Canceled'); 9 | return; 10 | } 11 | let wsedit = new vscode.WorkspaceEdit(); 12 | const path = `${uri.fsPath}/${className}.dart`; 13 | const filePath = vscode.Uri.file(path); 14 | wsedit.createFile(filePath); 15 | vscode.workspace.applyEdit(wsedit); 16 | const interfaceNameFile = _.upperFirst(_.camelCase(className)); 17 | fs.writeFileSync(path, `class ${interfaceNameFile} { 18 | 19 | }`, 'utf8'); 20 | vscode.workspace.openTextDocument(path).then(doc => { 21 | vscode.window.showTextDocument(doc); 22 | }); 23 | vscode.window.showInformationMessage('Created a Dart Class'); 24 | } 25 | 26 | function promptForFeatureName(prompt) { 27 | const FeatureNamePromptOptions = { 28 | prompt: prompt, 29 | placeHolder: "Class Name" 30 | }; 31 | return vscode.window.showInputBox(FeatureNamePromptOptions); 32 | } 33 | 34 | module.exports = {generateClass}; -------------------------------------------------------------------------------- /src/commands/generate_construtor.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | const { findClassContentAtPosition } = require('../utils/class_content_helper'); 5 | 6 | async function generateNamedConstructor(uri) { 7 | const editor = vscode.window.activeTextEditor; 8 | if (!editor) { 9 | return; // Nenhum editor ativo 10 | } 11 | const cursorPosition = editor.selection.start; 12 | const text = findClassContentAtPosition(editor.document.getText(), cursorPosition); 13 | const className = getClassName(text); 14 | const fields = getClassFields(text); 15 | 16 | if (className && fields.length > 0) { 17 | const constructor = generateNamedConstructorText(className, fields); 18 | insertText(constructor); 19 | } else { 20 | vscode.window.showInformationMessage('Nenhuma classe Dart válida encontrada'); 21 | } 22 | 23 | } 24 | 25 | function findInsertPosition(text) { 26 | const lines = text.split('\n'); 27 | let lastPropertyLineIndex = null; 28 | 29 | for (let i = 0; i < lines.length; i++) { 30 | if (isPropertyDeclaration(lines[i])) { 31 | lastPropertyLineIndex = i; 32 | } 33 | } 34 | 35 | if (lastPropertyLineIndex !== null) { 36 | return lastPropertyLineIndex + 1; 37 | } 38 | 39 | return null; 40 | } 41 | 42 | function isPropertyDeclaration(line) { 43 | // Esta regex busca por linhas que parecem ser declarações de propriedades em Dart 44 | return line.trim().match(/^\s*(?!.*\b(get|set)\b)(final|const|var)?\s*([\w<>,\?\s]+)?\s+(\w+)\s*;\s*$/gm); 45 | } 46 | 47 | 48 | function getClassFields(text) { 49 | // const fieldRegex = /^\s*(final|const|var)?\s*([\w<>,\?\s]+)?\s+(\w+)(\s*=\s*[^;]+;|;)/gm; 50 | const fieldRegex = /^\s*(?!.*\b(get|set)\b)(final|const|var)?\s*([\w<>,\?\s]+)?\s+(\w+)\s*;\s*$/gm; 51 | 52 | 53 | 54 | let match; 55 | const fields = []; 56 | 57 | while ((match = fieldRegex.exec(text)) !== null) { 58 | const type = match[3] ? match[3].trim() : 'dynamic'; 59 | const name = match[4].trim(); 60 | 61 | 62 | if(match[0].includes('final') && match[0].includes('=')){ 63 | vscode.window.showWarningMessage(`Field ${name} is already initialized and final, cannot add to constructor`); 64 | }else{ 65 | fields.push({ type: type, name: name }); 66 | } 67 | 68 | 69 | } 70 | 71 | 72 | 73 | return fields; 74 | } 75 | 76 | 77 | /** 78 | * Encontra o nome da classe no texto 79 | */ 80 | function getClassName(text) { 81 | const classRegex = /class\s+([a-zA-Z0-9_]+)\s+/; 82 | const match = classRegex.exec(text); 83 | return match ? match[1] : null; 84 | } 85 | 86 | 87 | /** 88 | * Gera o método copyWith 89 | */ 90 | function generateNamedConstructorText(className, fields) { 91 | 92 | const requireds = []; 93 | const normals = []; 94 | 95 | fields.forEach(field => { 96 | if (field.type.endsWith('?')) { 97 | normals.push(`this.${field.name}`) 98 | } else { 99 | requireds.push(`required this.${field.name}`); 100 | } 101 | }); 102 | 103 | let parameters = ''; 104 | const totalRequireds = requireds.length; 105 | if (totalRequireds > 0) { 106 | parameters = requireds.join(', ') 107 | } 108 | 109 | if (normals.length > 0) { 110 | parameters += totalRequireds > 0 ? `, ${normals.join(', ')}` : `${normals.join(', ')}` 111 | } 112 | 113 | return ` 114 | ${className}({${parameters},}); 115 | `; 116 | } 117 | 118 | /** 119 | * Insere o texto no editor 120 | */ 121 | async function insertText(text) { 122 | const editor = vscode.window.activeTextEditor; 123 | // const textEditor = editor.document.getText(); 124 | const textEditor = findClassContentAtPosition(editor.document.getText(), editor.selection.start); 125 | const insertPosition = findInsertPosition(textEditor); 126 | 127 | if (editor) { 128 | await editor.edit(editBuilder => { 129 | editBuilder.insert(new vscode.Position((editor.selection.start.line+1), 0), text + '\n'); 130 | }); 131 | await vscode.commands.executeCommand('editor.action.formatDocument'); 132 | } 133 | } 134 | 135 | module.exports = { generateNamedConstructor }; -------------------------------------------------------------------------------- /src/commands/generate_copy_with.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | const { findClassContentAtPosition } = require('../utils/class_content_helper'); 5 | 6 | async function generateCopyWith(uri) { 7 | const editor = vscode.window.activeTextEditor; 8 | if (!editor) { 9 | vscode.window.showInformationMessage('Nenhum arquivo aberto'); 10 | return; 11 | } 12 | 13 | const cursorPosition = editor.selection.start; 14 | const text = findClassContentAtPosition(editor.document.getText(), cursorPosition); 15 | const className = getClassName(text); 16 | const fields = getClassFields(text); 17 | 18 | if (className && fields.length > 0) { 19 | const copyWithMethod = generateCopyWithMethod(className, fields); 20 | insertText(copyWithMethod); 21 | } else { 22 | vscode.window.showInformationMessage('Nenhuma classe Dart válida encontrada'); 23 | } 24 | } 25 | 26 | 27 | /** 28 | * Encontra o nome da classe no texto 29 | */ 30 | function getClassName(text) { 31 | const classRegex = /class\s+([a-zA-Z0-9_]+)\s+/; 32 | const match = classRegex.exec(text); 33 | return match ? match[1] : null; 34 | } 35 | 36 | function getClassFields(text) { 37 | // const fieldRegex = /^\s*(final|const|var)?\s*([\w<>,\?\s]+)?\s+(\w+)(\s*=\s*[^;]+;|;)/gm; 38 | const fieldRegex = /^\s*(?!.*\b(get|set)\b)(final|const|var)?\s*([\w<>,\?\s]+)?\s+(\w+)\s*;\s*$/gm; 39 | 40 | let match; 41 | const fields = []; 42 | 43 | while ((match = fieldRegex.exec(text)) !== null) { 44 | let type = ''; 45 | 46 | if (!match[3] || (match[3] == 'final' || match[3] == 'const' || match[3] == 'var')) { 47 | type = 'dynamic'; 48 | } else { 49 | type = match[3].trim(); 50 | } 51 | 52 | const name = match[4].trim(); 53 | fields.push({ type: type, name: name }); 54 | } 55 | 56 | 57 | 58 | return fields; 59 | } 60 | 61 | 62 | /** 63 | * Gera o método copyWith 64 | */ 65 | function generateCopyWithMethod(className, fields) { 66 | const parameters = fields.map(field => { 67 | if (field.type.endsWith('?')) { 68 | return `ValueGetter<${field.type}>? ${field.name}` 69 | } else { 70 | return `${field.type}? ${field.name}` 71 | } 72 | 73 | }).join(', '); 74 | const assignments = fields.map(field => { 75 | if (field.type.endsWith('?')) { 76 | return `${field.name}: ${field.name} != null ? ${field.name}() : this.${field.name}` 77 | } else { 78 | return `${field.name}: ${field.name} ?? this.${field.name}` 79 | } 80 | 81 | }).join(',\n '); 82 | 83 | return ` 84 | ${className} copyWith({${parameters},}) { 85 | return ${className}( 86 | ${assignments}, 87 | ); 88 | } 89 | `; 90 | } 91 | 92 | function findPositionBeforeClosingBrace(text) { 93 | const lines = text.split('\n'); 94 | let lastBraceIndex = null; 95 | 96 | for (let i = lines.length - 1; i >= 0; i--) { 97 | if (lines[i].trim() === '}') { 98 | lastBraceIndex = i; 99 | break; 100 | } 101 | } 102 | 103 | if (lastBraceIndex !== null) { 104 | return new vscode.Position(lastBraceIndex, 0); 105 | } 106 | 107 | return null; 108 | } 109 | /** 110 | * Insere o texto no editor 111 | */ 112 | async function insertText(text) { 113 | const editor = vscode.window.activeTextEditor; 114 | const textEditor = editor.document.getText(); 115 | const insertPosition = findPositionBeforeClosingBrace(textEditor); 116 | 117 | if (editor) { 118 | await editor.edit(editBuilder => { 119 | editBuilder.insert(insertPosition, text); 120 | 121 | if (text.includes('ValueGetter') && !text.includes("import 'package:flutter/material.dart';")) { 122 | editBuilder.insert(new vscode.Position(0, 0), ` 123 | import 'package:flutter/material.dart';\n 124 | `); 125 | } 126 | 127 | 128 | }); 129 | await vscode.commands.executeCommand('editor.action.formatDocument'); 130 | 131 | } 132 | } 133 | 134 | module.exports = { generateCopyWith }; -------------------------------------------------------------------------------- /src/commands/generate_interface.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const _ = require('lodash'); 5 | 6 | async function generateInterface(uri) { 7 | let interfaceName = await promptForFeatureName("Interface Name"); 8 | if(!interfaceName){ 9 | vscode.window.showInformationMessage('Creating a Dart Interface Canceled'); 10 | return; 11 | } 12 | let wsedit = new vscode.WorkspaceEdit(); 13 | const configType = vscode.workspace.getConfiguration("generate").get("template.type"); 14 | if(configType == 'I Prefix') { 15 | if(!interfaceName.startsWith('i_')){ 16 | interfaceName = `i_${interfaceName}`; 17 | } 18 | } 19 | 20 | const path = `${uri.fsPath}/${interfaceName}.dart`; 21 | const filePath = vscode.Uri.file(path); 22 | wsedit.createFile(filePath); 23 | vscode.workspace.applyEdit(wsedit); 24 | const interfaceNameFile = _.upperFirst(_.camelCase(interfaceName)); 25 | 26 | fs.writeFileSync(path, `abstract class ${interfaceNameFile} { 27 | 28 | }`, 'utf8'); 29 | vscode.workspace.openTextDocument(path).then(doc => { 30 | vscode.window.showTextDocument(doc); 31 | }); 32 | vscode.window.showInformationMessage('Created a Dart Interface'); 33 | } 34 | 35 | function promptForFeatureName(prompt) { 36 | const FeatureNamePromptOptions = { 37 | prompt: prompt, 38 | placeHolder: "Interface Name" 39 | }; 40 | return vscode.window.showInputBox(FeatureNamePromptOptions); 41 | } 42 | 43 | module.exports = {generateInterface}; -------------------------------------------------------------------------------- /src/commands/generate_singleton_class.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | 5 | async function generateSingletonClass(uri) { 6 | const className = await promptForFeatureName("Class Name"); 7 | if (!className) { 8 | vscode.window.showInformationMessage('Creating a Dart Class Canceled'); 9 | return; 10 | } 11 | let wsedit = new vscode.WorkspaceEdit(); 12 | const path = `${uri.fsPath}/${className}.dart`; 13 | const filePath = vscode.Uri.file(path); 14 | wsedit.createFile(filePath); 15 | vscode.workspace.applyEdit(wsedit); 16 | const singletonNameFile = _.upperFirst(_.camelCase(className)); 17 | 18 | fs.writeFileSync(path, `class ${singletonNameFile} { 19 | static ${singletonNameFile}? _instance; 20 | // Avoid self instance 21 | ${singletonNameFile}._(); 22 | static ${singletonNameFile} get instance => _instance ??= ${singletonNameFile}._(); 23 | }`, 'utf8'); 24 | vscode.workspace.openTextDocument(path).then(doc => { 25 | vscode.window.showTextDocument(doc); 26 | }); 27 | vscode.window.showInformationMessage('Created a Dart Singleton Class'); 28 | } 29 | 30 | function promptForFeatureName(prompt) { 31 | const FeatureNamePromptOptions = { 32 | prompt: prompt, 33 | placeHolder: "Class Name" 34 | }; 35 | return vscode.window.showInputBox(FeatureNamePromptOptions); 36 | } 37 | 38 | module.exports = { 39 | generateSingletonClass 40 | }; -------------------------------------------------------------------------------- /src/commands/generate_stateful_widget.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | 5 | async function generateStatefulWidget(uri) { 6 | const widgetName = await promptForFeatureName("Widget Name"); 7 | if (!widgetName) { 8 | vscode.window.showInformationMessage('Creating a Statefull Widget Canceled'); 9 | return; 10 | } 11 | let wsedit = new vscode.WorkspaceEdit(); 12 | const path = `${uri.fsPath}/${widgetName}.dart`; 13 | const filePath = vscode.Uri.file(path); 14 | wsedit.createFile(filePath); 15 | vscode.workspace.applyEdit(wsedit); 16 | const widgetNameFile = _.upperFirst(_.camelCase(widgetName)); 17 | fs.writeFileSync(path, `import 'package:flutter/material.dart'; 18 | 19 | class ${widgetNameFile} extends StatefulWidget { 20 | const ${widgetNameFile}({Key? key}) : super(key: key); 21 | 22 | @override 23 | _${widgetNameFile}State createState() => _${widgetNameFile}State(); 24 | } 25 | 26 | class _${widgetNameFile}State extends State<${widgetNameFile}> { 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar( 31 | title: const Text(''), 32 | ), 33 | body: Container(), 34 | ); 35 | } 36 | }`, 'utf8'); 37 | vscode.workspace.openTextDocument(path).then(doc => { 38 | vscode.window.showTextDocument(doc); 39 | }); 40 | vscode.window.showInformationMessage('Created a StatelessWidget'); 41 | } 42 | 43 | function promptForFeatureName(prompt) { 44 | const FeatureNamePromptOptions = { 45 | prompt: prompt, 46 | placeHolder: "Widget Name" 47 | }; 48 | return vscode.window.showInputBox(FeatureNamePromptOptions); 49 | } 50 | 51 | module.exports = { generateStatefulWidget }; -------------------------------------------------------------------------------- /src/commands/generate_stateless_widget.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | 5 | async function generateStatelessWidget(uri) { 6 | const widgetName = await promptForFeatureName("Widget Name"); 7 | if (!widgetName) { 8 | vscode.window.showInformationMessage('Creating a Stateless Widget Canceled'); 9 | return; 10 | } 11 | let wsedit = new vscode.WorkspaceEdit(); 12 | const path = `${uri.fsPath}/${widgetName}.dart`; 13 | const filePath = vscode.Uri.file(path); 14 | wsedit.createFile(filePath); 15 | vscode.workspace.applyEdit(wsedit); 16 | const widgetNameFile = _.upperFirst(_.camelCase(widgetName)); 17 | fs.writeFileSync(path, `import 'package:flutter/material.dart'; 18 | 19 | class ${widgetNameFile} extends StatelessWidget { 20 | 21 | const ${widgetNameFile}({ Key? key }) : super(key: key); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return Scaffold( 26 | appBar: AppBar( 27 | title: const Text(''), 28 | ), 29 | body: Container(), 30 | ); 31 | } 32 | }`, 'utf8'); 33 | vscode.workspace.openTextDocument(path).then(doc => { 34 | vscode.window.showTextDocument(doc); 35 | }); 36 | vscode.window.showInformationMessage('Created a StatelessWidget'); 37 | } 38 | 39 | function promptForFeatureName(prompt) { 40 | const FeatureNamePromptOptions = { 41 | prompt: prompt, 42 | placeHolder: "Widget Name" 43 | }; 44 | return vscode.window.showInputBox(FeatureNamePromptOptions); 45 | } 46 | 47 | module.exports = { generateStatelessWidget }; -------------------------------------------------------------------------------- /src/commands/generate_test_file.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | 4 | async function generateTestFile(uri) { 5 | const pathTest = uri.fsPath.replace('/lib/', '/test/'); 6 | mkdirp(pathTest) 7 | vscode.window.showInformationMessage('Test Folder Generate' + pathTest); 8 | } 9 | 10 | module.exports = {generateTestFile}; -------------------------------------------------------------------------------- /src/commands/getx_new_feature.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const _ = require('lodash'); 5 | // const { wrapWithProviderConsumerBuilder, wrapWithValueListenableBuilder, wrapWithMobXObserverBuilder } = require('../commands/wrap-with'); 6 | const { createFile } = require('../commands/create_file'); 7 | 8 | async function getXNewFeature(uri) { 9 | const featureName = await promptForFeatureName("Feature GetX Name"); 10 | if (featureName) { 11 | mkdirp(uri.fsPath + '/' + featureName); 12 | const baseUrl = uri.fsPath + '/' + featureName 13 | const page = `${baseUrl}/${featureName}_page.dart`; 14 | const bindings = `${baseUrl}/${featureName}_bindings.dart`; 15 | const controller = `${baseUrl}/${featureName}_controller.dart`; 16 | 17 | await createFile(page); 18 | await createFile(bindings); 19 | await createFile(controller); 20 | 21 | const pageNameFile = _.upperFirst(_.camelCase(`${featureName}Page`)); 22 | const bindingNameFile = _.upperFirst(_.camelCase(`${featureName}Bindings`)); 23 | const controllerNameFile = _.upperFirst(_.camelCase(`${featureName}Controller`)); 24 | 25 | fs.writeFileSync(page, `import 'package:get/get.dart'; 26 | import 'package:flutter/material.dart'; 27 | import './${featureName}_controller.dart'; 28 | 29 | class ${pageNameFile} extends GetView<${controllerNameFile}> { 30 | 31 | const ${pageNameFile}({Key? key}) : super(key: key); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Scaffold( 36 | appBar: AppBar(title: const Text('${pageNameFile}'),), 37 | body: Container(), 38 | ); 39 | } 40 | }`, 'utf8'); 41 | 42 | fs.writeFileSync(bindings, `import 'package:get/get.dart'; 43 | import './${featureName}_controller.dart'; 44 | 45 | class ${bindingNameFile} implements Bindings { 46 | @override 47 | void dependencies() { 48 | Get.put(${controllerNameFile}()); 49 | } 50 | }`, 'utf8'); 51 | 52 | fs.writeFileSync(controller, `import 'package:get/get.dart'; 53 | 54 | class ${controllerNameFile} extends GetxController {}`, 'utf8'); 55 | 56 | vscode.window.showInformationMessage('GetX new feature created'); 57 | } 58 | } 59 | 60 | function promptForFeatureName(prompt) { 61 | const FeatureNamePromptOptions = { 62 | prompt: prompt, 63 | placeHolder: "Feature Name" 64 | }; 65 | return vscode.window.showInputBox(FeatureNamePromptOptions); 66 | } 67 | 68 | 69 | 70 | // vscode.commands.registerCommand("extension.getxfeature", async function (uri) { 71 | // const featureName = await promptForFeatureName("Feature GetX Name"); 72 | // if (featureName) { 73 | // mkdirp(uri.fsPath + '/' + featureName); 74 | // const baseUrl = uri.fsPath + '/' + featureName 75 | // const page = `${baseUrl}/${featureName}_page.dart`; 76 | // const bindings = `${baseUrl}/${featureName}_bindings.dart`; 77 | // const controller = `${baseUrl}/${featureName}_controller.dart`; 78 | 79 | // await createFile(page); 80 | // await createFile(bindings); 81 | // await createFile(controller); 82 | 83 | // const pageNameFile = _.upperFirst(_.camelCase(`${featureName}Page`)); 84 | // const bindingNameFile = _.upperFirst(_.camelCase(`${featureName}Bindings`)); 85 | // const controllerNameFile = _.upperFirst(_.camelCase(`${featureName}Controller`)); 86 | 87 | // fs.writeFileSync(page, `import 'package:get/get.dart'; 88 | // import 'package:flutter/material.dart'; 89 | // import './${featureName}_controller.dart'; 90 | 91 | // class ${pageNameFile} extends GetView<${controllerNameFile}> { 92 | // @override 93 | // Widget build(BuildContext context) { 94 | // return Scaffold( 95 | // appBar: AppBar(title: Text('${pageNameFile}'),), 96 | // body: Container(), 97 | // ); 98 | // } 99 | // }`, 'utf8'); 100 | 101 | // fs.writeFileSync(bindings, `import 'package:get/get.dart'; 102 | // import './${featureName}_controller.dart'; 103 | 104 | // class ${bindingNameFile} implements Bindings { 105 | // @override 106 | // void dependencies() { 107 | // Get.put(${controllerNameFile}()); 108 | // } 109 | // }`, 'utf8'); 110 | 111 | // fs.writeFileSync(controller, `import 'package:get/get.dart'; 112 | 113 | // class ${controllerNameFile} extends GetxController {}`, 'utf8'); 114 | 115 | // vscode.window.showInformationMessage('GetX new feature created'); 116 | // } 117 | // }); 118 | 119 | module.exports = {getXNewFeature}; -------------------------------------------------------------------------------- /src/commands/implements_interface.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const pathImp = require('path'); 4 | const _ = require('lodash'); 5 | const { isDart3 } = require('../utils/getDartSdkVersion'); 6 | const { getContentTemplate } = require('./templates/read_file_template'); 7 | 8 | async function implementsInterface(uri) { 9 | let editor = vscode.window.activeTextEditor; 10 | const textFile = editor.document.getText(); 11 | 12 | let stringSearch = 'abstract class '; 13 | if (isDart3()) { 14 | stringSearch = 'interface class '; 15 | 16 | if (textFile.includes('abstract interface')) { 17 | stringSearch = 'abstract interface class '; 18 | } 19 | } 20 | 21 | const indexStart = textFile.lastIndexOf(stringSearch); 22 | let indexEnd = textFile.indexOf(' {'); 23 | 24 | if (indexEnd === -1) { 25 | indexEnd = textFile.indexOf('{'); 26 | } 27 | 28 | if (indexEnd === -1) { 29 | vscode.window.showErrorMessage('please format the code before running the implements interface'); 30 | return; 31 | } 32 | 33 | if (textFile.includes('extends')) { 34 | indexEnd = textFile.indexOf(' extends'); 35 | } else if (textFile.includes('with')) { 36 | indexEnd = textFile.indexOf(' with'); 37 | } 38 | 39 | let interfaceName = textFile.substring(indexStart, indexEnd).replace(stringSearch, ' ').replace(' {', ''); 40 | interfaceName = interfaceName.trimRight(); 41 | const configType = vscode.workspace.getConfiguration("generate").get("template.type"); 42 | let implementationName = interfaceName.trim(); 43 | if (configType === 'I Prefix') { 44 | implementationName = interfaceName.replace('I', ''); 45 | } else if (configType === 'Clean Code') { 46 | implementationName = interfaceName + 'Impl'; 47 | } else { 48 | let suffixClass = await promptForFeatureName(); 49 | if (suffixClass == undefined) { 50 | return; 51 | } else if (suffixClass === '') { 52 | suffixClass = 'Impl'; 53 | } 54 | implementationName = interfaceName + suffixClass; 55 | } 56 | 57 | let wsedit = new vscode.WorkspaceEdit(); 58 | const basePath = editor.document.uri.fsPath.replace(`${_.snakeCase(interfaceName)}.dart`, ''); 59 | if (basePath) { 60 | const path = `${basePath}/${_.snakeCase(implementationName)}.dart`; 61 | const filePath = vscode.Uri.file(path); 62 | wsedit.createFile(filePath); 63 | vscode.workspace.applyEdit(wsedit); 64 | let templateClass = getContentTemplate(pathImp.join('dart','class_implements.template')); 65 | 66 | templateClass = templateClass.replace("##IMPORT_NAME##", _.snakeCase(interfaceName)); 67 | templateClass = templateClass.replace("##CLASS_NAME##", implementationName.trim()); 68 | templateClass = templateClass.replace("##INTERFACE_NAME##", interfaceName.trim()); 69 | 70 | 71 | fs.writeFileSync(path, templateClass, 'utf-8'); 72 | 73 | 74 | vscode.workspace.openTextDocument(path).then(async doc => { 75 | vscode.window.showTextDocument(doc); 76 | }); 77 | 78 | } 79 | } 80 | 81 | function promptForFeatureName() { 82 | const FeatureNamePromptOptions = { 83 | prompt: 'Choice suffix name, if empty then add Impl', 84 | placeHolder: "Choice suffix name", 85 | describe: 'teste' 86 | }; 87 | return vscode.window.showInputBox(FeatureNamePromptOptions); 88 | } 89 | 90 | 91 | module.exports = { implementsInterface }; -------------------------------------------------------------------------------- /src/commands/import_gist.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const { default: axios } = require('axios'); 3 | 4 | async function importGist(uri) { 5 | let editor = vscode.window.activeTextEditor; 6 | 7 | const gistId = await promptForFeatureName("Gist ID", "bff92c45073837310f630527100462ca"); 8 | 9 | if (gistId !== null && gistId !== "") { 10 | const mainFile = await readGistFile(gistId); 11 | editor.edit(editBuilder => { 12 | const currentPosition = editor.selection.active; 13 | 14 | editBuilder.insert(currentPosition, `${mainFile}`); 15 | }) 16 | 17 | } 18 | 19 | } 20 | 21 | async function readGistFile(gistId) { 22 | try { 23 | const url = `https://api.github.com/gists/${gistId}`; 24 | const response = await axios.get(url); 25 | const gist = response.data; 26 | 27 | if (gist.files && gist.files['main.dart']) { 28 | const fileUrl = gist.files['main.dart'].raw_url; 29 | const fileResponse = await axios.get(fileUrl); 30 | return fileResponse.data; 31 | } else { 32 | vscode.window.showErrorMessage('main.dart file not found'); 33 | } 34 | } catch (error) { 35 | console.error(error); 36 | } 37 | } 38 | 39 | function promptForFeatureName(prompt, placeHolder = '') { 40 | const FeatureNamePromptOptions = { 41 | prompt: prompt, 42 | placeHolder: placeHolder 43 | }; 44 | return vscode.window.showInputBox(FeatureNamePromptOptions); 45 | } 46 | 47 | 48 | 49 | module.exports = { importGist }; -------------------------------------------------------------------------------- /src/commands/inherit_class.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | const { getContentTemplate } = require('./templates/read_file_template'); 5 | const pathImp = require('path'); 6 | 7 | async function inheritClass(uri) { 8 | let editor = vscode.window.activeTextEditor; 9 | const textFile = editor.document.getText(); 10 | 11 | let stringSearch = 'abstract class '; 12 | 13 | const indexStart = textFile.lastIndexOf(stringSearch); 14 | let indexEnd = textFile.indexOf(' {'); 15 | 16 | if (indexEnd === -1) { 17 | indexEnd = textFile.indexOf('{'); 18 | } 19 | 20 | if (indexEnd === -1) { 21 | vscode.window.showErrorMessage('please format the code before running the implements interface'); 22 | return; 23 | } 24 | 25 | if (textFile.includes('extends')) { 26 | indexEnd = textFile.indexOf(' extends'); 27 | } else if (textFile.includes('with')) { 28 | indexEnd = textFile.indexOf(' with'); 29 | } 30 | 31 | let interfaceName = textFile.substring(indexStart, indexEnd).replace(stringSearch, ' ').replace(' {', ''); 32 | interfaceName = interfaceName.trimRight(); 33 | const configType = vscode.workspace.getConfiguration("generate").get("template.type"); 34 | let implementationName = interfaceName.trim(); 35 | if (configType === 'I Prefix') { 36 | implementationName = interfaceName.replace('I', ''); 37 | } else if (configType === 'Clean Code') { 38 | implementationName = interfaceName + 'Impl'; 39 | } else { 40 | let suffixClass = await promptForFeatureName(); 41 | if (suffixClass == undefined) { 42 | return; 43 | } else if (suffixClass === '') { 44 | suffixClass = 'Impl'; 45 | } 46 | implementationName = interfaceName + suffixClass; 47 | } 48 | 49 | let wsedit = new vscode.WorkspaceEdit(); 50 | const basePath = editor.document.uri.fsPath.replace(`${_.snakeCase(interfaceName)}.dart`, ''); 51 | if (basePath) { 52 | const path = `${basePath}/${_.snakeCase(implementationName)}.dart`; 53 | const filePath = vscode.Uri.file(path); 54 | wsedit.createFile(filePath); 55 | vscode.workspace.applyEdit(wsedit); 56 | let templateClass = getContentTemplate(pathImp.join('dart', 'inherit_class.template')); 57 | 58 | templateClass = templateClass.replace("##IMPORT_NAME##", _.snakeCase(interfaceName)); 59 | templateClass = templateClass.replace("##CLASS_NAME##", implementationName.trim()); 60 | templateClass = templateClass.replace("##EXTENDS_NAME##", interfaceName.trim()); 61 | 62 | 63 | fs.writeFileSync(path, templateClass, 'utf-8'); 64 | 65 | 66 | vscode.workspace.openTextDocument(path).then(async doc => { 67 | vscode.window.showTextDocument(doc); 68 | }); 69 | 70 | } 71 | } 72 | 73 | function promptForFeatureName() { 74 | const FeatureNamePromptOptions = { 75 | prompt: 'Choice suffix name, if empty then add Impl', 76 | placeHolder: "Choice suffix name", 77 | describe: 'teste' 78 | }; 79 | return vscode.window.showInputBox(FeatureNamePromptOptions); 80 | } 81 | 82 | 83 | module.exports = { inheritClass }; -------------------------------------------------------------------------------- /src/commands/json_serializable_generate_json_key.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | const { getContentTemplate } = require('./templates/read_file_template'); 5 | 6 | async function jsonSerializableGenerateJsonKey(uri) { 7 | const editor = vscode.window.activeTextEditor; 8 | 9 | if (editor) { 10 | const document = editor.document; 11 | const selection = editor.selection; 12 | const position = editor.selection.active; 13 | const line = selection.start.line; 14 | const lineText = editor.document.lineAt(position.line); 15 | var text = lineText.text; 16 | // text = text.replace('final', ''); 17 | // text = text.replace('var', ''); 18 | const range = /(.*?)(?:\s*=|\s*;)/.exec(text.trim()); 19 | 20 | if (range) { 21 | // const text = document.getText(range); 22 | const match = range[1].split(' '); 23 | if (match) { 24 | if(match.length >= 3){ 25 | match.shift(); 26 | } 27 | const name = match[match.length == 1 ? 0 : 1].replace('_', ''); 28 | const replacedText = name.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase(); 29 | 30 | await editor.edit(editBuilder => { 31 | 32 | const position = line === 0 ? 0 : line; 33 | const newPosition = new vscode.Position(position, 0); 34 | const textToAdd = "@JsonKey(name: '"+ replacedText + "')\n"; 35 | editBuilder.insert(newPosition, textToAdd); 36 | }); 37 | await vscode.commands.executeCommand('editor.action.formatDocument'); 38 | } 39 | }else { 40 | 41 | } 42 | 43 | } 44 | } 45 | 46 | 47 | 48 | module.exports = { jsonSerializableGenerateJsonKey }; -------------------------------------------------------------------------------- /src/commands/modular_initial_config.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const _ = require('lodash'); 6 | 7 | const { createFile } = require('../commands/create_file'); 8 | 9 | async function modularInitialConfig(uri) { 10 | 11 | const basePathName = await promptForFeatureName("Specify the base folder of your project (app, src, or /). Leave it blank to add it to the src folder.", "src") || 'src'; 12 | const basePath = uri.fsPath; 13 | 14 | mkdirp(`${basePath}/${basePathName}/modules/home/`); 15 | 16 | const mainDartFile = `${basePath}/main.dart`; 17 | const appModuleDartFile = `${basePath}/${basePathName}/app_module.dart`; 18 | const appWidgetDartFile = `${basePath}/${basePathName}/app_widget.dart`; 19 | const homePageDartFile = `${basePath}/${basePathName}/modules/home/home_page.dart`; 20 | 21 | await createFile(mainDartFile); 22 | await createFile(appModuleDartFile); 23 | await createFile(appWidgetDartFile); 24 | await createFile(homePageDartFile); 25 | 26 | 27 | const baseExtensionPath = vscode.extensions.getExtension('RodrigoRahman.flutter-dart-utils').extensionPath; 28 | const basePathTemplate = `${baseExtensionPath}/src/commands/templates/modular`; 29 | 30 | createFileByTemplate(`${basePathTemplate}/main.template`, mainDartFile, basePathName); 31 | createFileByTemplate(`${basePathTemplate}/app_module.template`, appModuleDartFile, basePathName); 32 | createFileByTemplate(`${basePathTemplate}/app_widget.template`, appWidgetDartFile, basePathName); 33 | createFileByTemplate(`${basePathTemplate}/home_page.template`, homePageDartFile, basePathName); 34 | 35 | } 36 | 37 | function promptForFeatureName(prompt, placeHolder = 'Feature Name') { 38 | const FeatureNamePromptOptions = { 39 | prompt: prompt, 40 | placeHolder: placeHolder 41 | }; 42 | return vscode.window.showInputBox(FeatureNamePromptOptions); 43 | } 44 | 45 | function createFileByTemplate(templatePath, filePath, basePath) { 46 | fs.readFile(templatePath, 'utf8', (err, data) => { 47 | if (err) { 48 | console.log(err); 49 | } 50 | 51 | const bodyFile = data.replace(/##BASE_PATH##/g, basePath); 52 | fs.writeFile(filePath, bodyFile, { flag: 'w' }, (err) => { 53 | if (err) throw err; 54 | console.log('Arquivo salvo com sucesso!'); 55 | }); 56 | }); 57 | } 58 | 59 | module.exports = { modularInitialConfig }; -------------------------------------------------------------------------------- /src/commands/modular_new_feature.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const _ = require('lodash'); 5 | // const { wrapWithProviderConsumerBuilder, wrapWithValueListenableBuilder, wrapWithMobXObserverBuilder } = require('../commands/wrap-with'); 6 | const { createFile } = require('../commands/create_file'); 7 | 8 | async function modularNewFeature(uri) { 9 | const featureName = await promptForFeatureName("Modular Feature Name"); 10 | if (featureName) { 11 | mkdirp(uri.fsPath + '/' + featureName); 12 | const baseUrl = uri.fsPath + '/' + featureName 13 | const page = `${baseUrl}/${featureName}_page.dart`; 14 | const modularModule = `${baseUrl}/${featureName}_module.dart`; 15 | const controller = `${baseUrl}/${featureName}_controller.dart`; 16 | 17 | await createFile(page); 18 | await createFile(modularModule); 19 | await createFile(controller); 20 | 21 | const pageNameFile = _.upperFirst(_.camelCase(`${featureName}Page`)); 22 | const moduleNameFile = _.upperFirst(_.camelCase(`${featureName}Module`)); 23 | const controllerNameFile = _.upperFirst(_.camelCase(`${featureName}Controller`)); 24 | 25 | fs.writeFileSync(page, `import 'package:flutter/material.dart'; 26 | import './${featureName}_controller.dart'; 27 | 28 | class ${pageNameFile} extends StatelessWidget { 29 | 30 | final ${controllerNameFile} _controller; 31 | 32 | const ${pageNameFile}({ 33 | Key? key, 34 | required ${controllerNameFile} controller, 35 | }) : _controller = controller; 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | return Scaffold( 40 | appBar: AppBar(title: Text('${pageNameFile}'),), 41 | body: Container(), 42 | ); 43 | } 44 | }`, 'utf8'); 45 | 46 | fs.writeFileSync(modularModule, `import 'package:flutter_modular/flutter_modular.dart'; 47 | import './${featureName}_controller.dart'; 48 | import './${featureName}_page.dart'; 49 | 50 | class ${moduleNameFile} extends Module { 51 | @override 52 | final List binds = [ 53 | Bind.lazySingleton((i) => ${controllerNameFile}()), 54 | ]; 55 | 56 | @override 57 | final List routes = [ 58 | ChildRoute('/', child: (_, args) => ${pageNameFile}(controller: Modular.get())), 59 | ]; 60 | 61 | }`, 'utf8'); 62 | 63 | fs.writeFileSync(controller, `import 'package:mobx/mobx.dart'; 64 | 65 | part '${featureName}_controller.g.dart'; 66 | 67 | class ${controllerNameFile} = _${controllerNameFile}Base with _$${controllerNameFile}; 68 | 69 | abstract class _${controllerNameFile}Base with Store { 70 | 71 | } 72 | 73 | `, 'utf8'); 74 | 75 | vscode.window.showInformationMessage('Modular new feature created'); 76 | } 77 | } 78 | 79 | function promptForFeatureName(prompt) { 80 | const FeatureNamePromptOptions = { 81 | prompt: prompt, 82 | placeHolder: "Feature Name" 83 | }; 84 | return vscode.window.showInputBox(FeatureNamePromptOptions); 85 | } 86 | 87 | 88 | 89 | module.exports = {modularNewFeature}; -------------------------------------------------------------------------------- /src/commands/mvc_feature.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const _ = require('lodash'); 5 | // const { wrapWithProviderConsumerBuilder, wrapWithValueListenableBuilder, wrapWithMobXObserverBuilder } = require('../commands/wrap-with'); 6 | const { createFile } = require('../commands/create_file'); 7 | const path = require('path'); 8 | 9 | async function mvnfeature(uri) { 10 | const featureName = await promptForFeatureName("MVC Feature Name"); 11 | if (featureName) { 12 | mkdirp(path.join(uri.fsPath , featureName)); 13 | const baseUrl = path.join(uri.fsPath , featureName); 14 | mkdirp(path.join(baseUrl , '/model')).catch((err) => console.log(err)); 15 | mkdirp(path.join(baseUrl , '/view_models')).catch((err) => console.log(err)); 16 | mkdirp(path.join(baseUrl , '/view')).catch((err) => console.log(err)); 17 | mkdirp(path.join(baseUrl , '/controller')).catch((err) => console.log(err)); 18 | } 19 | 20 | } 21 | 22 | function promptForFeatureName(prompt) { 23 | const FeatureNamePromptOptions = { 24 | prompt: prompt, 25 | placeHolder: "Feature 3 Tiers Name" 26 | }; 27 | return vscode.window.showInputBox(FeatureNamePromptOptions); 28 | } 29 | module.exports = {mvnfeature} -------------------------------------------------------------------------------- /src/commands/snake_case_transform.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const fs = require('fs'); 3 | const _ = require('lodash'); 4 | const { getContentTemplate } = require('./templates/read_file_template'); 5 | const pathImp = require('path'); 6 | 7 | async function snakeCaseTransform(uri) { 8 | const editor = vscode.window.activeTextEditor; 9 | 10 | if (editor) { 11 | const document = editor.document; 12 | const selection = editor.selection; 13 | 14 | const text = document.getText(selection); 15 | 16 | const replacedText = text.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase(); 17 | 18 | editor.edit(editBuilder => { 19 | editBuilder.replace(selection, replacedText); 20 | }); 21 | } 22 | } 23 | 24 | 25 | 26 | module.exports = { snakeCaseTransform }; -------------------------------------------------------------------------------- /src/commands/templates/dart/class_implements.template: -------------------------------------------------------------------------------- 1 | import './##IMPORT_NAME##.dart'; 2 | 3 | class ##CLASS_NAME## implements ##INTERFACE_NAME## { 4 | 5 | } -------------------------------------------------------------------------------- /src/commands/templates/dart/inherit_class.template: -------------------------------------------------------------------------------- 1 | import './##IMPORT_NAME##.dart'; 2 | 3 | class ##CLASS_NAME## extends ##EXTENDS_NAME## { 4 | 5 | } -------------------------------------------------------------------------------- /src/commands/templates/fvm/settings.template: -------------------------------------------------------------------------------- 1 | { 2 | "dart.flutterSdkPath": ".fvm/flutter_sdk", 3 | // Remove .fvm files from search 4 | "search.exclude": { 5 | "**/.fvm": true 6 | }, 7 | // Remove from file watching 8 | "files.watcherExclude": { 9 | "**/.fvm": true 10 | } 11 | } -------------------------------------------------------------------------------- /src/commands/templates/modular/app_module.template: -------------------------------------------------------------------------------- 1 | import 'package:flutter_modular/flutter_modular.dart'; 2 | import './modules/home/home_page.dart'; 3 | 4 | 5 | class AppModule extends Module { 6 | @override 7 | List get binds => []; 8 | 9 | @override 10 | List get routes => [ 11 | ChildRoute('/', child: (context, args) => const HomePage()), 12 | ]; 13 | } -------------------------------------------------------------------------------- /src/commands/templates/modular/app_widget.template: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_modular/flutter_modular.dart'; 3 | 4 | class AppWidget extends StatelessWidget { 5 | const AppWidget({super.key}); 6 | 7 | @override 8 | Widget build(BuildContext context){ 9 | return MaterialApp.router( 10 | title: 'Application Name', 11 | theme: ThemeData(primarySwatch: Colors.blue), 12 | routeInformationParser: Modular.routeInformationParser, 13 | routerDelegate: Modular.routerDelegate, 14 | ); 15 | } 16 | } -------------------------------------------------------------------------------- /src/commands/templates/modular/home_page.template: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class HomePage extends StatelessWidget { 4 | 5 | const HomePage({ super.key }); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | return Scaffold( 10 | appBar: AppBar(title: const Text('Home Page'),), 11 | body: Container(), 12 | ); 13 | } 14 | } -------------------------------------------------------------------------------- /src/commands/templates/modular/main.template: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_modular/flutter_modular.dart'; 3 | import './##BASE_PATH##/app_module.dart'; 4 | import './##BASE_PATH##/app_widget.dart'; 5 | 6 | void main(){ 7 | return runApp(ModularApp(module: AppModule(), child: const AppWidget())); 8 | } -------------------------------------------------------------------------------- /src/commands/templates/read_file_template.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const vscode = require('vscode'); 3 | function getContentTemplate(templatePath) { 4 | const baseExtensionPath = vscode.extensions.getExtension('RodrigoRahman.flutter-dart-utils').extensionPath; 5 | const finalTemplatePath = `${baseExtensionPath}/src/commands/templates/${templatePath}`; 6 | 7 | return fs.readFileSync(finalTemplatePath, 'utf8'); 8 | } 9 | 10 | module.exports = { getContentTemplate }; -------------------------------------------------------------------------------- /src/commands/three_tiers.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const mkdirp = require('mkdirp'); 3 | const fs = require('fs'); 4 | const _ = require('lodash'); 5 | // const { wrapWithProviderConsumerBuilder, wrapWithValueListenableBuilder, wrapWithMobXObserverBuilder } = require('../commands/wrap-with'); 6 | const { createFile } = require('../commands/create_file'); 7 | const path = require('path'); 8 | 9 | async function three_tiers(uri) { 10 | const featureName = await promptForFeatureName("Feature 3 Tiers Name"); 11 | if (featureName) { 12 | mkdirp(path.join(uri.fsPath, featureName)) 13 | const baseUrl = path.join(uri.fsPath , featureName); 14 | mkdirp(path.join(baseUrl ,'/data')).catch((err) => console.log(err)); 15 | mkdirp(path.join(baseUrl ,'/controller')).catch((err) => console.log(err)); 16 | mkdirp(path.join(baseUrl ,'/service')).catch((err) => console.log(err)); 17 | mkdirp(path.join(baseUrl ,'/view_models')).catch((err) => console.log(err)); 18 | } 19 | 20 | } 21 | 22 | function promptForFeatureName(prompt) { 23 | const FeatureNamePromptOptions = { 24 | prompt: prompt, 25 | placeHolder: "Feature 3 Tiers Name" 26 | }; 27 | return vscode.window.showInputBox(FeatureNamePromptOptions); 28 | } 29 | module.exports = {three_tiers} -------------------------------------------------------------------------------- /src/commands/wrap-with.js: -------------------------------------------------------------------------------- 1 | const wrapWith = require('../utils/wrap-with'); 2 | 3 | const valueListenableBuilderSnippet = (widget) => { 4 | return `ValueListenableBuilder( 5 | valueListenable: $1, 6 | builder: (_, $1Value, child) { 7 | return ${widget}; 8 | }, 9 | )`; 10 | }; 11 | 12 | 13 | const providerConsumerBuilderSnippet = (widget) => { 14 | return `Consumer<$1>( 15 | builder: (_, $2, __) { 16 | return ${widget}; 17 | }, 18 | )`; 19 | }; 20 | 21 | const mobxObserverBuilderSnippet = (widget) => { 22 | return `Observer( 23 | builder: (_) { 24 | return ${widget}; 25 | }, 26 | )`; 27 | }; 28 | 29 | const layoutBuilderSnippet = (widget) => { 30 | return `LayoutBuilder( 31 | builder: (_, constrains) { 32 | return ${widget}; 33 | }, 34 | )`; 35 | }; 36 | 37 | const builderSnippet = (widget) => { 38 | return `Builder( 39 | builder: (context) { 40 | return ${widget}; 41 | }, 42 | )`; 43 | }; 44 | 45 | const obxSnippet = (widget) => { 46 | return `Obx(() { 47 | return ${widget}; 48 | } 49 | )`; 50 | }; 51 | 52 | const getXSnippet = (widget) => { 53 | return `GetX<$1>( 54 | init: $1(), 55 | initState: (_) {}, 56 | builder: (_) { 57 | return ${widget}; 58 | }, 59 | )`; 60 | }; 61 | 62 | const watchSignalsSnippet = (widget) => { 63 | return `Watch((_) { 64 | return ${widget}; 65 | }, 66 | )`; 67 | }; 68 | 69 | 70 | const wrapWithValueListenableBuilder = async () => wrapWith(valueListenableBuilderSnippet); 71 | const wrapWithProviderConsumerBuilder = async () => wrapWith(providerConsumerBuilderSnippet); 72 | const wrapWithMobXObserverBuilder = async () => wrapWith(mobxObserverBuilderSnippet); 73 | const wrapWithLayoutBuilder = async () => wrapWith(layoutBuilderSnippet); 74 | const wrapWithBuilder = async () => wrapWith(builderSnippet); 75 | const wrapWithObxGetX = async () => wrapWith(obxSnippet); 76 | const wrapWithGetx = async () => wrapWith(getXSnippet); 77 | const wrapWithSignals = async () => wrapWith(watchSignalsSnippet); 78 | 79 | module.exports = { wrapWithValueListenableBuilder, wrapWithProviderConsumerBuilder, wrapWithMobXObserverBuilder, wrapWithLayoutBuilder, wrapWithBuilder, wrapWithObxGetX, wrapWithGetx, wrapWithSignals }; -------------------------------------------------------------------------------- /src/extension.js: -------------------------------------------------------------------------------- 1 | // The module 'vscode' contains the VS Code extensibility API 2 | // Import the module and reference it with the alias vscode in your code below 3 | const vscode = require('vscode'); 4 | const fs = require('fs'); 5 | const _ = require('lodash'); 6 | const { wrapWithProviderConsumerBuilder, wrapWithValueListenableBuilder, wrapWithMobXObserverBuilder, wrapWithLayoutBuilder, wrapWithBuilder, wrapWithObxGetX, wrapWithGetx, wrapWithSignals } = require('./commands/wrap-with'); 7 | const { getXNewFeature } = require('./commands/getx_new_feature'); 8 | const { createCleanArchFolders } = require('./commands/clean_arch_folders'); 9 | const { createCleanArchFoldersForFlutter } = require('./commands/clean_arch_folders_for_flutter'); 10 | const { generateTestFile } = require('./commands/generate_test_file'); 11 | const { generateInterface } = require('./commands/generate_interface'); 12 | const { generateClass } = require('./commands/generate_class'); 13 | const { generateSingletonClass } = require('./commands/generate_singleton_class'); 14 | const { generateStatelessWidget } = require('./commands/generate_stateless_widget'); 15 | const { generateStatefulWidget } = require('./commands/generate_stateful_widget'); 16 | const { implementsInterface: implementsInterfaceFun } = require('./commands/implements_interface'); 17 | const { importGist: importGistFun } = require('./commands/import_gist'); 18 | const { three_tiers } = require('./commands/three_tiers'); 19 | const { mvnfeature } = require('./commands/mvc_feature'); 20 | const { modularNewFeature } = require('./commands/modular_new_feature'); 21 | const { modularInitialConfig } = require('./commands/modular_initial_config'); 22 | const path = require('path'); 23 | 24 | 25 | const { isDart3, isDart } = require('./utils/getDartSdkVersion'); 26 | const { inheritClass } = require('./commands/inherit_class'); 27 | const { fvmConfigure } = require('./commands/fvm_configure'); 28 | const { fvmInstallConfigure } = require('./commands/fvm_install_configure'); 29 | const { snakeCaseTransform } = require('./commands/snake_case_transform'); 30 | const { jsonSerializableGenerateJsonKey } = require('./commands/json_serializable_generate_json_key'); 31 | const { createGetter } = require('./commands/create_getter'); 32 | const { generateCopyWith } = require('./commands/generate_copy_with'); 33 | const { generateNamedConstructor } = require('./commands/generate_construtor'); 34 | const { isCursorOnClassDeclaration, isCursorOnAttributeDeclaration } = require('./utils/class_content_helper'); 35 | 36 | 37 | 38 | function snippetHit(context) { 39 | if (isDart3()) { 40 | saveSnippet(context, 'dart.json', path.join('dart', 'dart3.json')); 41 | saveSnippet(context, 'flutter.json', path.join('flutter', 'flutter3.10.json')); 42 | } else { 43 | saveSnippet(context, 'dart.json', path.join('dart', 'dart2.json')); 44 | if (isDart("2.17.0")) { 45 | saveSnippet(context, 'flutter.json', path.join('flutter', 'flutter2.17.json')); 46 | } else { 47 | saveSnippet(context, 'flutter.json', path.join('flutter', 'flutter2.json')); 48 | } 49 | 50 | } 51 | } 52 | 53 | 54 | function saveSnippet(context, snippetName, snippetFile) { 55 | const snippetsPath = path.join(context.extensionPath, 'snippets', snippetFile); 56 | const snippetsContent = fs.readFileSync(snippetsPath, 'utf8'); 57 | 58 | const snippetsFinalPath = path.join(context.extensionPath, 'snippets', snippetName); 59 | 60 | fs.writeFileSync(snippetsFinalPath, snippetsContent); 61 | } 62 | 63 | /** 64 | * @param {vscode.ExtensionContext} context 65 | */ 66 | function activate(context) { 67 | snippetHit(context); 68 | const modularfeature = vscode.commands.registerCommand("extension.modularfeature", modularNewFeature); 69 | const modularInitial = vscode.commands.registerCommand("extension.modulariniital", modularInitialConfig); 70 | const getxfeature = vscode.commands.registerCommand("extension.getxfeature", getXNewFeature); 71 | 72 | const disposable = vscode.commands.registerCommand("extension.clean-architecture-folders", createCleanArchFolders); 73 | 74 | const cleanForFlutter = vscode.commands.registerCommand("extension.clean-architecture-folders-for-flutter", createCleanArchFoldersForFlutter); 75 | 76 | const disposableGenerateTest = vscode.commands.registerCommand('extension.generateTestFile', generateTestFile); 77 | 78 | const createInterface = vscode.commands.registerCommand('extension.generateInterface', generateInterface); 79 | 80 | const createClass = vscode.commands.registerCommand('extension.generateClass', generateClass); 81 | const createSingletonClass = vscode.commands.registerCommand('extension.generateSingletonClass', generateSingletonClass); 82 | const createStatelessWidget = vscode.commands.registerCommand('extension.generateStatelessWidget', generateStatelessWidget); 83 | const createStatefulWidget = vscode.commands.registerCommand('extension.generateStatefulWidget', generateStatefulWidget); 84 | 85 | vscode.commands.registerCommand('extension.implementsInterface', implementsInterfaceFun); 86 | vscode.commands.registerCommand('extension.importGist', importGistFun); 87 | vscode.commands.registerCommand('extension.inheritClass', inheritClass); 88 | vscode.commands.registerCommand('extension.snakeCaseTransform', snakeCaseTransform); 89 | vscode.commands.registerCommand('extension.jsonSerializableGenerateJsonKey', jsonSerializableGenerateJsonKey); 90 | vscode.commands.registerCommand('extension.createGetter', createGetter); 91 | vscode.commands.registerCommand('extension.generateCopyWith', generateCopyWith); 92 | vscode.commands.registerCommand('extension.generateNamedConstructor', generateNamedConstructor); 93 | 94 | const threeTiersFolders = vscode.commands.registerCommand("extension.3-tiers", three_tiers); 95 | 96 | const MVCFlutterFolders = vscode.commands.registerCommand("extension.mvc-feature", mvnfeature); 97 | const fvmConfigureCommand = vscode.commands.registerCommand("extension.fvmConfigure", fvmConfigure); 98 | const fvmInstallConfigureCommand = vscode.commands.registerCommand("extension.fvmInstallConfigure", fvmInstallConfigure); 99 | vscode.commands.registerCommand('extension.fu-wrap-with-value-notifier', wrapWithValueListenableBuilder); 100 | vscode.commands.registerCommand('extension.fu-wrap-with-consumer', wrapWithProviderConsumerBuilder); 101 | vscode.commands.registerCommand('extension.fu-wrap-with-observer', wrapWithMobXObserverBuilder); 102 | vscode.commands.registerCommand('extension.fu-wrap-with-layout-builder', wrapWithLayoutBuilder); 103 | vscode.commands.registerCommand('extension.fu-wrap-with-builder', wrapWithBuilder); 104 | vscode.commands.registerCommand('extension.fu-wrap-with-obx-getx', wrapWithObxGetX); 105 | vscode.commands.registerCommand('extension.fu-wrap-with-getx', wrapWithGetx); 106 | vscode.commands.registerCommand('extension.fu-wrap-with-watch-signals', wrapWithSignals); 107 | 108 | context.subscriptions.push( 109 | vscode.languages.registerCodeActionsProvider( 110 | { pattern: "**/*.{dart,dartx}", scheme: "file" }, 111 | new CodeActionProvider() 112 | ), 113 | disposable, 114 | disposableGenerateTest, 115 | cleanForFlutter, 116 | createInterface, 117 | createClass, 118 | createSingletonClass, 119 | createStatelessWidget, 120 | createStatefulWidget, 121 | threeTiersFolders, 122 | MVCFlutterFolders, 123 | getxfeature, 124 | modularfeature, 125 | modularInitial, 126 | fvmConfigureCommand, 127 | fvmInstallConfigureCommand 128 | ); 129 | } 130 | 131 | 132 | class CodeActionProvider { 133 | provideCodeActions() { 134 | const editor = vscode.window.activeTextEditor; 135 | if (!editor) { 136 | return []; 137 | } 138 | 139 | 140 | const textFile = editor.document.getText(); 141 | const codeActions = []; 142 | 143 | 144 | if (isDart3() && textFile.includes('abstract class')) { 145 | codeActions.push({ command: 'extension.inheritClass', title: 'Extends Class' }) 146 | } 147 | 148 | const pickedText = editor.document.getText(editor.selection); 149 | 150 | if (pickedText.length > 2) { 151 | codeActions.push({ command: 'extension.snakeCaseTransform', title: 'Snake Case Transform' }); 152 | } 153 | 154 | if (isCursorOnClassDeclaration()) { 155 | codeActions.push({ command: 'extension.generateCopyWith', title: 'Generate CopyWith' }); 156 | codeActions.push({ command: 'extension.generateNamedConstructor', title: 'Generate Constructor with named params' }); 157 | } 158 | 159 | if (isCursorOnAttributeDeclaration()) { 160 | codeActions.push({ command: 'extension.jsonSerializableGenerateJsonKey', title: 'Add JsonKey from json_serializable' }); 161 | codeActions.push({ command: 'extension.createGetter', title: 'Generate Getter' }); 162 | } 163 | 164 | 165 | if (textFile.includes(isDart3() ? 'interface' : 'abstract')) { 166 | codeActions.push({ 167 | command: "extension.implementsInterface", 168 | title: "Implements interface" 169 | }); 170 | } 171 | 172 | 173 | 174 | if (textFile === '') { 175 | codeActions.push({ command: 'extension.importGist', title: 'Import GitHub Gist from id' }) 176 | } 177 | 178 | 179 | if (pickedText === '') { 180 | return codeActions 181 | }; 182 | 183 | if (textFile.includes('build(BuildContext context)') || textFile.includes('build(context)')) { 184 | codeActions.push( 185 | { 186 | command: "extension.fu-wrap-with-layout-builder", 187 | title: "Wrap with LayoutBuilder" 188 | } 189 | ); 190 | codeActions.push( 191 | { 192 | command: "extension.fu-wrap-with-builder", 193 | title: "Wrap with Builder" 194 | } 195 | ); 196 | 197 | codeActions.push( 198 | { 199 | command: "extension.fu-wrap-with-obx-getx", 200 | title: "Wrap with Obx" 201 | } 202 | ); 203 | 204 | codeActions.push( 205 | { 206 | command: "extension.fu-wrap-with-getx", 207 | title: "Wrap with GetX" 208 | } 209 | ); 210 | 211 | codeActions.push( 212 | { 213 | command: "extension.fu-wrap-with-value-notifier", 214 | title: "Wrap with ValueListenableBuilder" 215 | }); 216 | 217 | codeActions.push( 218 | { 219 | command: "extension.fu-wrap-with-consumer", 220 | title: "Wrap with Consumer" 221 | } 222 | ); 223 | codeActions.push( 224 | { 225 | command: "extension.fu-wrap-with-observer", 226 | title: "Wrap with MobX Observer" 227 | } 228 | ); 229 | 230 | codeActions.push( 231 | { 232 | command: "extension.fu-wrap-with-watch-signals", 233 | title: "Wrap with Watch of Signals" 234 | } 235 | ); 236 | } 237 | 238 | 239 | return codeActions; 240 | } 241 | } 242 | 243 | // this method is called when your extension is deactivated 244 | function deactivate() { } 245 | 246 | 247 | module.exports = { 248 | activate, 249 | deactivate 250 | } 251 | 252 | 253 | -------------------------------------------------------------------------------- /src/utils/class_content_helper.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | 3 | function isCursorOnClassDeclaration() { 4 | const editor = vscode.window.activeTextEditor; 5 | const position = editor.selection.active; 6 | const lineText = editor.document.lineAt(position.line).text; 7 | 8 | return /^\s*(final\s+)?class\s+\w+/.test(lineText); 9 | 10 | } 11 | 12 | function isCursorOnAttributeDeclaration() { 13 | const editor = vscode.window.activeTextEditor; 14 | if (!editor) { 15 | return false; // Nenhum editor ativo 16 | } 17 | 18 | const position = editor.selection.active; 19 | const lineText = editor.document.lineAt(position.line).text; 20 | 21 | // A expressão regular para identificar declarações de atributos 22 | const attributeRegex = /^\s*(final\s+)?[\w?<>[\]]+\s+\w+(\s*=\s*[^;]+;|;)/; 23 | 24 | return attributeRegex.test(lineText); 25 | } 26 | 27 | function findClassContentAtPosition(text, position) { 28 | const lines = text.split('\n'); 29 | let classDeclarationLine = -1; 30 | 31 | // Encontrar a linha onde a declaração da classe começa 32 | for (let i = position.line; i <= lines.length; i++) { 33 | if (lines[i].includes('class ')) { 34 | classDeclarationLine = i; 35 | break; 36 | } 37 | } 38 | 39 | if (classDeclarationLine === -1) { 40 | return null; // Nenhuma declaração de classe encontrada 41 | } 42 | 43 | // Extrair o conteúdo da classe 44 | let braceCount = 0; 45 | let classContent = ''; 46 | for (let i = classDeclarationLine; i < lines.length; i++) { 47 | if (lines[i].includes('{')) { 48 | braceCount++; 49 | } 50 | if (braceCount > 0) { 51 | classContent += lines[i] + '\n'; 52 | } 53 | if (lines[i].includes('}')) { 54 | braceCount--; 55 | if (braceCount === 0) { 56 | break; // Fim da classe 57 | } 58 | } 59 | } 60 | 61 | return classContent; 62 | } 63 | module.exports = { findClassContentAtPosition, isCursorOnClassDeclaration, isCursorOnAttributeDeclaration }; -------------------------------------------------------------------------------- /src/utils/get-class-content.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rodrigorahman/flutter-dart-utils-vscode/fb8b04336905ca0877652753fd64d6e72f1146db/src/utils/get-class-content.js -------------------------------------------------------------------------------- /src/utils/get-selected-text.js: -------------------------------------------------------------------------------- 1 | const { Selection } = require("vscode"); 2 | 3 | const getSelectedText = (editor) => { 4 | return editor.selection; 5 | 6 | // let offset_l = editor.document.offsetAt(editor.selection.start); 7 | // let offset_r = editor.document.offsetAt(editor.selection.end) - 1; 8 | // let text = editor.document.getText(); 9 | // const re = /[^a-zA-Z]/; 10 | // for (let index = text.length - offset_l; index > 0; index--) { 11 | // let textOff = text.charAt(offset_l); 12 | // if (textOff !== "." && re.test(textOff)) { 13 | // offset_l++; 14 | // if (/[^A-Z]/.test(text.charAt(offset_l))) { 15 | // return new Selection( 16 | // editor.document.positionAt(0), 17 | // editor.document.positionAt(0) 18 | // ); 19 | // } 20 | // let lineText = editor.document.lineAt( 21 | // editor.document.positionAt(offset_l).line 22 | // ).text; 23 | // if ( 24 | // lineText.indexOf("class") != -1 || 25 | // lineText.indexOf("extends") != -1 || 26 | // lineText.indexOf("with") != -1 || 27 | // lineText.indexOf("implements") != -1 || 28 | // lineText.indexOf("=") != -1 29 | // ) { 30 | // return new Selection( 31 | // editor.document.positionAt(0), 32 | // editor.document.positionAt(0) 33 | // ); 34 | // } 35 | 36 | // break; 37 | // } else { 38 | // offset_l--; 39 | // } 40 | // } 41 | // let l = 0; 42 | // let r = 0; 43 | // for (let index = text.length - offset_r; index < text.length; index++) { 44 | // if (text.charAt(offset_r) === "(") { 45 | // l++; 46 | // } 47 | // if (text.charAt(offset_r) === ")") { 48 | // r++; 49 | // } 50 | 51 | // if (r > l || index == text.length) { 52 | // offset_r = 0; 53 | // offset_l = 0; 54 | // break; 55 | // } 56 | 57 | // if (l > 0 && l == r) { 58 | // offset_r++; 59 | // if (!nextElementIsValid(text, offset_r)) { 60 | // offset_r = 0; 61 | // offset_l = 0; 62 | // } 63 | // break; 64 | // } 65 | // offset_r++; 66 | // } 67 | 68 | // return new Selection( 69 | // editor.document.positionAt(offset_l), 70 | // editor.document.positionAt(offset_r) 71 | // ); 72 | }; 73 | 74 | const nextElementIsValid = (code, length) => { 75 | for (let index = 0; index < 1000; index++) { 76 | const text = code.charAt(length).trim(); 77 | if (text) { 78 | if (/[;),\]]/.test(text)) { 79 | return true; 80 | } else { 81 | return false; 82 | } 83 | } 84 | length++; 85 | } 86 | return false; 87 | }; 88 | 89 | module.exports = getSelectedText; -------------------------------------------------------------------------------- /src/utils/getDartSdkVersion.js: -------------------------------------------------------------------------------- 1 | const yaml = require('js-yaml'); 2 | const path = require('path'); 3 | const semver = require('semver'); 4 | const vscode = require('vscode'); 5 | const fs = require('fs'); 6 | const semverMajor = require('semver/functions/major'); 7 | const { forEach } = require('lodash'); 8 | 9 | 10 | let dartSDK = null; 11 | let _isDart3 = null; 12 | 13 | function getRootPath() { 14 | return vscode.workspace.workspaceFolders[0].uri.fsPath; 15 | } 16 | 17 | function getDartSDKVersion(context) { 18 | return dartSDK ?? readDartSDK(context) 19 | } 20 | 21 | function readDartSDK(context) { 22 | const pubspecPath = path.join(getRootPath(), 'pubspec.yaml'); 23 | 24 | const pubspecContent = fs.readFileSync(pubspecPath, 'utf8'); 25 | 26 | const pubspec = yaml.load(pubspecContent); 27 | 28 | // Obtém a versão do SDK Dart 29 | dartSDK = pubspec['environment'].sdk; 30 | return dartSDK; 31 | 32 | } 33 | 34 | function isDart3() { 35 | 36 | if (_isDart3 != null) { 37 | return _isDart3; 38 | } 39 | 40 | const dartSDK = getDartSDKVersion(); 41 | const versions = dartSDK.split(' '); 42 | for (let version in versions) { 43 | _isDart3 = semver.gt(semver.coerce(versions[version]), '3.0.0'); 44 | if (!_isDart3) { 45 | _isDart3 = false; 46 | break; 47 | } 48 | } 49 | return _isDart3; 50 | } 51 | 52 | function isDart(versionCheck) { 53 | 54 | const dartSDK = getDartSDKVersion(); 55 | const versions = dartSDK.split(' '); 56 | for (let version in versions) { 57 | _isDart3 = semver.gt(semver.coerce(versions[version]), versionCheck); 58 | if (!_isDart3) { 59 | _isDart3 = false; 60 | break; 61 | } 62 | } 63 | return _isDart3; 64 | } 65 | 66 | 67 | module.exports = { isDart3, isDart }; -------------------------------------------------------------------------------- /src/utils/wrap-with.js: -------------------------------------------------------------------------------- 1 | // import { window, commands, SnippetString } from "vscode"; 2 | const { window, commands, SnippetString } = require('vscode'); 3 | const getSelectedText = require('./get-selected-text'); 4 | 5 | const wrapWith = async (snippet) => { 6 | let editor = window.activeTextEditor; 7 | if (!editor) return; 8 | const selection = getSelectedText(editor); 9 | const widget = editor.document.getText(selection); 10 | editor.insertSnippet(new SnippetString(snippet(widget)), selection); 11 | await commands.executeCommand("editor.action.formatDocument"); 12 | }; 13 | 14 | 15 | module.exports = wrapWith; -------------------------------------------------------------------------------- /test/runTest.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const { runTests } = require('vscode-test'); 4 | 5 | async function main() { 6 | try { 7 | // The folder containing the Extension Manifest package.json 8 | // Passed to `--extensionDevelopmentPath` 9 | const extensionDevelopmentPath = path.resolve(__dirname, '../'); 10 | 11 | // The path to the extension test script 12 | // Passed to --extensionTestsPath 13 | const extensionTestsPath = path.resolve(__dirname, './suite/index'); 14 | 15 | // Download VS Code, unzip it and run the integration test 16 | await runTests({ extensionDevelopmentPath, extensionTestsPath }); 17 | } catch (err) { 18 | console.error('Failed to run tests'); 19 | process.exit(1); 20 | } 21 | } 22 | 23 | main(); 24 | -------------------------------------------------------------------------------- /test/suite/extension.test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | // You can import and use all API from the 'vscode' module 4 | // as well as import your extension to test it 5 | const vscode = require('vscode'); 6 | // const myExtension = require('../extension'); 7 | 8 | suite('Extension Test Suite', () => { 9 | vscode.window.showInformationMessage('Start all tests.'); 10 | 11 | test('Sample test', () => { 12 | assert.equal(-1, [1, 2, 3].indexOf(5)); 13 | assert.equal(-1, [1, 2, 3].indexOf(0)); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/suite/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const Mocha = require('mocha'); 3 | const glob = require('glob'); 4 | 5 | function run() { 6 | // Create the mocha test 7 | const mocha = new Mocha({ 8 | ui: 'tdd', 9 | color: true 10 | }); 11 | 12 | const testsRoot = path.resolve(__dirname, '..'); 13 | 14 | return new Promise((c, e) => { 15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 16 | if (err) { 17 | return e(err); 18 | } 19 | 20 | // Add files to the test suite 21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 22 | 23 | try { 24 | // Run the mocha test 25 | mocha.run(failures => { 26 | if (failures > 0) { 27 | e(new Error(`${failures} tests failed.`)); 28 | } else { 29 | c(); 30 | } 31 | }); 32 | } catch (err) { 33 | console.error(err); 34 | e(err); 35 | } 36 | }); 37 | }); 38 | } 39 | 40 | module.exports = { 41 | run 42 | }; 43 | -------------------------------------------------------------------------------- /vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | 5 | * This folder contains all of the files necessary for your extension. 6 | * `package.json` - this is the manifest file in which you declare your extension and command. 7 | * 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. 8 | * `extension.js` - this is the main file where you will provide the implementation of your command. 9 | * 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`. 10 | * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. 11 | 12 | ## Get up and running straight away 13 | 14 | * Press `F5` to open a new window with your extension loaded. 15 | * Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. 16 | * Set breakpoints in your code inside `extension.js` to debug your extension. 17 | * Find output from your extension in the debug console. 18 | 19 | ## Make changes 20 | 21 | * You can relaunch the extension from the debug toolbar after changing code in `extension.js`. 22 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 23 | 24 | ## Explore the API 25 | 26 | * You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. 27 | 28 | ## Run tests 29 | 30 | * Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`. 31 | * Press `F5` to run the tests in a new window with your extension loaded. 32 | * See the output of the test result in the debug console. 33 | * Make changes to `src/test/suite/extension.test.js` or create new test files inside the `test/suite` folder. 34 | * The provided test runner will only consider files matching the name pattern `**.test.ts`. 35 | * You can create folders inside the `test` folder to structure your tests any way you want. 36 | ## Go further 37 | 38 | * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace. 39 | * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). 40 | --------------------------------------------------------------------------------