diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9f7b685 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: Run CI jobs +on: [push, pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '22' + - run: npm install + - run: npm run lint + + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '22' + - run: npm install + - run: xvfb-run -a npm test diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 016fc7d..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: lint -on: [push, pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: '22' - - run: npm install - - run: npm run lint \ No newline at end of file diff --git a/.vscode-test.mjs b/.vscode-test.mjs index b62ba25..87074fd 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -1,5 +1,5 @@ import { defineConfig } from '@vscode/test-cli'; export default defineConfig({ - files: 'out/test/**/*.test.js', + files: ['dist/test/setup.js', 'dist/test/**/*.test.js'], }); diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3cf99c3..e6d85fe 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,64 +1,46 @@ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format { - "version": "2.0.0", - "tasks": [ - { - "label": "watch", - "dependsOn": [ - "npm: watch:tsc", - "npm: watch:esbuild" - ], - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "type": "npm", - "script": "watch:esbuild", - "group": "build", - "problemMatcher": "$esbuild-watch", - "isBackground": true, - "label": "npm: watch:esbuild", - "presentation": { - "group": "watch", - "reveal": "never" - } - }, - { - "type": "npm", - "script": "watch:tsc", - "group": "build", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "label": "npm: watch:tsc", - "presentation": { - "group": "watch", - "reveal": "never" - } - }, - { - "type": "npm", - "script": "watch-tests", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never", - "group": "watchers" - }, - "group": "build" - }, - { - "label": "tasks: watch-tests", - "dependsOn": [ - "npm: watch", - "npm: watch-tests" - ], - "problemMatcher": [] - } - ] + "version": "2.0.0", + "tasks": [ + { + "label": "watch", + "dependsOn": ["npm: watch:esbuild"], + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "npm", + "script": "watch:esbuild", + "group": "build", + "problemMatcher": "$esbuild-watch", + "isBackground": true, + "label": "npm: watch:esbuild", + "presentation": { + "group": "watch", + "reveal": "never" + } + }, + { + "type": "npm", + "script": "watch-tests", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never", + "group": "watchers" + }, + "group": "build" + }, + { + "label": "tasks: watch-tests", + "dependsOn": ["npm: watch", "npm: watch-tests"], + "problemMatcher": [] + } + ] } diff --git a/esbuild.test.js b/esbuild.test.js new file mode 100644 index 0000000..4519408 --- /dev/null +++ b/esbuild.test.js @@ -0,0 +1,89 @@ +const esbuild = require('esbuild'); +const fs = require('fs'); +const path = require('path'); + +const production = process.argv.includes('--production'); +const watch = process.argv.includes('--watch'); + +/** + * @type {import('esbuild').Plugin} + */ +const esbuildProblemMatcherPlugin = { + name: 'esbuild-problem-matcher', + + setup(build) { + build.onStart(() => { + console.log('[watch] test build started'); + }); + build.onEnd(result => { + result.errors.forEach(({ text, location }) => { + console.error(`✘ [ERROR] ${text}`); + console.error(` ${location.file}:${location.line}:${location.column}:`); + }); + console.log('[watch] test build finished'); + }); + }, +}; + +/** + * @type {import('esbuild').Plugin} + */ +const copyAssetsPlugin = { + name: 'copy-assets', + setup(build) { + build.onEnd(() => { + const copyDir = (src, dest) => { + if (!fs.existsSync(dest)) { + fs.mkdirSync(dest, { recursive: true }); + } + + const entries = fs.readdirSync(src, { withFileTypes: true }); + + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + copyDir(srcPath, destPath); + } else { + fs.copyFileSync(srcPath, destPath); + } + } + }; + + copyDir('test-resources', 'dist/test-resources'); + }); + }, +}; + +async function main() { + // Test build context + const testCtx = await esbuild.context({ + entryPoints: ['src/test/**/*.ts'], + bundle: true, + format: 'cjs', + minify: production, + sourcemap: true, + sourcesContent: !production, + platform: 'node', + outdir: 'dist/test', + define: { + 'process.env.NODE_ENV': JSON.stringify(production ? 'production' : 'development'), + }, + external: ['vscode', 'mocha'], + logLevel: 'info', + plugins: [esbuildProblemMatcherPlugin, copyAssetsPlugin], + }); + + if (watch) { + await testCtx.watch(); + } else { + await testCtx.rebuild(); + await testCtx.dispose(); + } +} + +main().catch(e => { + console.error(e); + process.exit(1); +}); diff --git a/eslint.config.mjs b/eslint.config.mjs index 45d9dc9..d12ffcd 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,7 +5,7 @@ import eslintConfigPrettier from 'eslint-config-prettier'; export default [ { - files: ['**/*.ts', '**/*.tsx'], + files: ['src/**/*.ts', 'src/**/*.tsx'], }, { plugins: { diff --git a/package-lock.json b/package-lock.json index 0adc065..000090d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@types/node": "20.x", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", + "@types/sinon": "^17.0.4", "@types/validatorjs": "^3.15.5", "@types/vscode": "^1.93.1", "@types/vscode-webview": "^1.57.5", @@ -50,6 +51,8 @@ "eslint-plugin-prettier": "^5.2.3", "npm-run-all": "^4.1.5", "prettier": "^3.4.2", + "rimraf": "^6.0.1", + "sinon": "^19.0.2", "typescript": "^5.7.2", "vsce": "^2.15.0" }, @@ -820,6 +823,50 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", + "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "lodash.get": "^4.4.2", + "type-detect": "^4.1.0" + } + }, + "node_modules/@sinonjs/samsam/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true + }, "node_modules/@types/ejs": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", @@ -900,6 +947,21 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/sinon": { + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.4.tgz", + "integrity": "sha512-RHnIrhfPO3+tJT0s7cFaXGZvsL4bbR3/k7z3P312qMS4JaS2Tk+KiwiLx1S0rQ56ERj00u1/BtdyVd0FY+Pdew==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -4037,6 +4099,12 @@ "setimmediate": "^1.0.5" } }, + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", + "dev": true + }, "node_modules/keytar": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", @@ -4165,6 +4233,13 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4559,6 +4634,19 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node_modules/nise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", + "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", + "just-extend": "^6.2.0", + "path-to-regexp": "^8.1.0" + } + }, "node_modules/node-abi": { "version": "3.74.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz", @@ -5162,6 +5250,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -5464,11 +5561,6 @@ "node": ">=8.10.0" } }, - "node_modules/reflect-metadata": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", - "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" - }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -5586,6 +5678,25 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", + "dev": true, + "dependencies": { + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5928,6 +6039,45 @@ "simple-concat": "^1.0.0" } }, + "node_modules/sinon": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", + "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.2", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/slugify": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", @@ -6439,6 +6589,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -6546,6 +6705,11 @@ "tslib": "^2.3.0" } }, + "node_modules/typescript-json-serializer/node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, "node_modules/typescript-memoize": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/typescript-memoize/-/typescript-memoize-1.1.1.tgz", diff --git a/package.json b/package.json index a05494a..534437d 100644 --- a/package.json +++ b/package.json @@ -189,14 +189,13 @@ }, "scripts": { "vscode:prepublish": "npm run package", - "compile": "npm run check-types && npm run lint && node esbuild.js", + "compile": "rimraf dist && npm run check-types && npm run lint && node esbuild.js", "watch": "npm-run-all -p watch:*", "watch:esbuild": "node esbuild.js --watch", - "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", - "package": "npm run check-types && npm run lint && node esbuild.js --production", - "compile-tests": "tsc -p . --outDir out", - "watch-tests": "tsc -p . -w --outDir out", - "pretest": "npm run compile-tests && npm run compile && npm run lint", + "watch:test": "node esbuild.test.js --watch", + "package": "npm run build", + "compile-tests": "node esbuild.test.js", + "pretest": "npm run compile && npm run compile-tests && npm run lint", "check-types": "tsc --noEmit", "lint": "eslint src", "test": "vscode-test", @@ -211,6 +210,7 @@ "@types/node": "20.x", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", + "@types/sinon": "^17.0.4", "@types/validatorjs": "^3.15.5", "@types/vscode": "^1.93.1", "@types/vscode-webview": "^1.57.5", @@ -224,6 +224,8 @@ "eslint-plugin-prettier": "^5.2.3", "npm-run-all": "^4.1.5", "prettier": "^3.4.2", + "rimraf": "^6.0.1", + "sinon": "^19.0.2", "typescript": "^5.7.2", "vsce": "^2.15.0" }, diff --git a/src/extension.ts b/src/extension.ts index 37e5e7d..d656c2c 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -12,7 +12,6 @@ import DocumentCache from 'cache/DocumentCache'; import GenerateContextPluginCommand from 'command/GenerateContextPluginCommand'; import { XmlClasslikeDefinitionProvider } from 'definition/XmlClasslikeDefinitionProvider'; import CopyMagentoPathCommand from 'command/CopyMagentoPathCommand'; -import Common from 'util/Common'; import GenerateXmlCatalogCommand from 'command/GenerateXmlCatalogCommand'; import XmlClasslikeHoverProvider from 'hover/XmlClasslikeHoverProvider'; import ObserverCodelensProvider from 'codelens/ObserverCodelensProvider'; @@ -26,6 +25,7 @@ import GenerateDiXmlFileCommand from 'command/GenerateDiXmlFileCommand'; import GeneratePreferenceCommand from 'command/GeneratePreferenceCommand'; import Magento from 'util/Magento'; import { WorkspaceFolder } from 'vscode'; +import Logger from 'util/Logger'; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed @@ -63,7 +63,7 @@ export async function activate(context: vscode.ExtensionContext) { commands.forEach(command => { const instance = new command(); - Common.log('Registering command', instance.getCommand()); + Logger.log('Registering command', instance.getCommand()); const disposable = vscode.commands.registerCommand(instance.getCommand(), async (...args) => { try { @@ -138,7 +138,7 @@ export async function activate(context: vscode.ExtensionContext) { DiagnosticCollectionProvider.updateDiagnostics(vscode.window.activeTextEditor.document); } - console.log('[Magento Toolbox] Loaded'); + return context; } // This method is called when your extension is deactivated diff --git a/src/generator/XmlGenerator.ts b/src/generator/XmlGenerator.ts index 0132d43..1f7df20 100644 --- a/src/generator/XmlGenerator.ts +++ b/src/generator/XmlGenerator.ts @@ -13,6 +13,7 @@ export default class XmlGenerator { const builder = new XMLBuilder({ attributeNamePrefix: '@_', ignoreAttributes: false, + oneListGroup: true, textNodeName: '#text', indentBy: ' ', format: true, diff --git a/src/generator/block/BlockClassGenerator.ts b/src/generator/block/BlockClassGenerator.ts index faf113b..d3566de 100644 --- a/src/generator/block/BlockClassGenerator.ts +++ b/src/generator/block/BlockClassGenerator.ts @@ -15,7 +15,8 @@ export default class BlockClassGenerator extends FileGenerator { public async generate(workspaceUri: Uri): Promise { const [vendor, module] = this.data.module.split('_'); - const namespaceParts = [vendor, module, this.data.path]; + const pathParts = this.data.path.split('/'); + const namespaceParts = [vendor, module, ...pathParts]; const moduleDirectory = Magento.getModuleDirectory(vendor, module, workspaceUri); const header = FileHeader.getHeader(this.data.module); diff --git a/src/generator/module/ModuleComposerGenerator.ts b/src/generator/module/ModuleComposerGenerator.ts index 1647180..8a50f79 100644 --- a/src/generator/module/ModuleComposerGenerator.ts +++ b/src/generator/module/ModuleComposerGenerator.ts @@ -27,13 +27,13 @@ export default class ModuleComposerGenerator extends FileGenerator { name: this.data.composerName, description: this.data.composerDescription, type: 'magento2-module', - license: this.data.license, + license: this.data.license.toUpperCase(), 'minimum-stability': 'dev', require: {}, autoload: { files: ['registration.php'], psr4: { - [namespace.toString() + '\\']: 'src/', + [namespace.toString() + '\\']: '', }, }, }; diff --git a/src/generator/module/ModuleXmlGenerator.ts b/src/generator/module/ModuleXmlGenerator.ts index af769e5..633e627 100644 --- a/src/generator/module/ModuleXmlGenerator.ts +++ b/src/generator/module/ModuleXmlGenerator.ts @@ -25,7 +25,7 @@ export default class ModuleXmlGenerator extends FileGenerator { protected getXmlContent(): string { const moduleName = Magento.getModuleName(this.data.vendor, this.data.module); - const xml = { + const xml: any = { '?xml': { '@_version': '1.0', }, @@ -38,7 +38,18 @@ export default class ModuleXmlGenerator extends FileGenerator { }, }; + if (this.data.sequence.length > 0) { + xml.config.module.sequence = this.data.sequence.map(module => ({ + module: { + '@_name': module, + }, + })); + } + const xmlGenerator = new XmlGenerator(xml); - return xmlGenerator.toString(); + return xmlGenerator.toString({ + unpairedTags: ['module'], + suppressUnpairedNode: false, + }); } } diff --git a/src/generator/observer/ObserverClassGenerator.ts b/src/generator/observer/ObserverClassGenerator.ts index 219186e..5a6a4a4 100644 --- a/src/generator/observer/ObserverClassGenerator.ts +++ b/src/generator/observer/ObserverClassGenerator.ts @@ -17,7 +17,8 @@ export default class ObserverClassGenerator extends FileGenerator { public async generate(workspaceUri: Uri): Promise { const [vendor, module] = this.data.module.split('_'); - const namespaceParts = [vendor, module, this.data.directoryPath]; + const pathParts = this.data.directoryPath.split('/'); + const namespaceParts = [vendor, module, ...pathParts]; const moduleDirectory = Magento.getModuleDirectory(vendor, module, workspaceUri); const phpFile = new PhpFile(); diff --git a/src/generator/observer/ObserverEventsGenerator.ts b/src/generator/observer/ObserverEventsGenerator.ts index 521821c..4d1768b 100644 --- a/src/generator/observer/ObserverEventsGenerator.ts +++ b/src/generator/observer/ObserverEventsGenerator.ts @@ -7,6 +7,7 @@ import indentString from 'indent-string'; import PhpNamespace from 'common/PhpNamespace'; import FindOrCreateEventsXml from 'generator/util/FindOrCreateEventsXml'; import Magento from 'util/Magento'; +import FileHeader from 'common/xml/FileHeader'; export default class ObserverDiGenerator extends FileGenerator { public constructor(protected data: ObserverWizardData) { diff --git a/src/generator/plugin/PluginClassGenerator.ts b/src/generator/plugin/PluginClassGenerator.ts index 304eda0..cf25460 100644 --- a/src/generator/plugin/PluginClassGenerator.ts +++ b/src/generator/plugin/PluginClassGenerator.ts @@ -75,7 +75,7 @@ export default class PluginClassGenerator extends FileGenerator { const printer = new PsrPrinter(); return new GeneratedFile( - Uri.joinPath(moduleDirectory, 'Plugin', `${pluginName}.php`), + Uri.joinPath(moduleDirectory, 'Plugin', ...nameParts, `${pluginName}.php`), printer.printFile(phpFile) ); } diff --git a/src/generator/preference/PreferenceClassGenerator.ts b/src/generator/preference/PreferenceClassGenerator.ts index a8780ef..070130d 100644 --- a/src/generator/preference/PreferenceClassGenerator.ts +++ b/src/generator/preference/PreferenceClassGenerator.ts @@ -13,7 +13,8 @@ export default class PreferenceClassGenerator extends FileGenerator { public async generate(workspaceUri: Uri): Promise { const [vendor, module] = this.data.module.split('_'); - const namespaceParts = [vendor, module, this.data.directory]; + const directoryParts = this.data.directory.split('/'); + const namespaceParts = [vendor, module, ...directoryParts]; const moduleDirectory = Magento.getModuleDirectory(vendor, module, workspaceUri); const header = FileHeader.getHeader(this.data.module); diff --git a/src/generator/preference/PreferenceDiGenerator.ts b/src/generator/preference/PreferenceDiGenerator.ts index 12f03f7..1666527 100644 --- a/src/generator/preference/PreferenceDiGenerator.ts +++ b/src/generator/preference/PreferenceDiGenerator.ts @@ -14,6 +14,10 @@ export default class PreferenceDiGenerator extends FileGenerator { public async generate(workspaceUri: Uri): Promise { const [vendor, module] = this.data.module.split('_'); + const directoryParts = this.data.directory.split('/'); + const namespaceParts = [vendor, module, ...directoryParts, this.data.className]; + const typeNamespace = namespaceParts.join('\\'); + const etcDirectory = Magento.getModuleDirectory(vendor, module, workspaceUri, 'etc'); const diFile = Magento.getUriWithArea(etcDirectory, 'di.xml', this.data.area); const diXml = await FindOrCreateDiXml.execute(workspaceUri, vendor, module, this.data.area); @@ -21,7 +25,7 @@ export default class PreferenceDiGenerator extends FileGenerator { const pluginXml = await GenerateFromTemplate.generate('xml/preference', { forClass: this.data.parentClass, - typeClass: this.data.className, + typeClass: typeNamespace, }); const newDiXml = diff --git a/src/generator/util/FindOrCreateEventsXml.ts b/src/generator/util/FindOrCreateEventsXml.ts index 6533163..450ee5b 100644 --- a/src/generator/util/FindOrCreateEventsXml.ts +++ b/src/generator/util/FindOrCreateEventsXml.ts @@ -2,6 +2,7 @@ import { Uri } from 'vscode'; import FileSystem from 'util/FileSystem'; import GenerateFromTemplate from './GenerateFromTemplate'; import { MagentoScope } from 'types'; +import FileHeader from 'common/xml/FileHeader'; export default class FindOrCreateEventsXml { public static async execute( @@ -26,6 +27,10 @@ export default class FindOrCreateEventsXml { return await FileSystem.readFile(eventsFile); } - return await GenerateFromTemplate.generate('xml/blank-events'); + const fileHeader = FileHeader.getHeader(`${vendor}_${module}`); + + return await GenerateFromTemplate.generate('xml/blank-events', { + fileHeader, + }); } } diff --git a/src/generator/util/GenerateFromTemplate.ts b/src/generator/util/GenerateFromTemplate.ts index 702a5e5..50dede4 100644 --- a/src/generator/util/GenerateFromTemplate.ts +++ b/src/generator/util/GenerateFromTemplate.ts @@ -1,7 +1,9 @@ import { render } from 'ejs'; import { resolve } from 'path'; import FileSystem from 'util/FileSystem'; +import Logger from 'util/Logger'; import { Uri } from 'vscode'; + export default class GenerateFromTemplate { public static async generate(template: string, data?: any): Promise { try { @@ -16,6 +18,6 @@ export default class GenerateFromTemplate { } protected static getTemplatePath(templateName: string): string { - return resolve(__dirname, 'templates', templateName + '.ejs'); + return resolve(FileSystem.getExtensionPath('templates'), templateName + '.ejs'); } } diff --git a/src/indexer/IndexManager.ts b/src/indexer/IndexManager.ts index 3cb97cf..14bf6f2 100644 --- a/src/indexer/IndexManager.ts +++ b/src/indexer/IndexManager.ts @@ -12,6 +12,7 @@ import { DiIndexData } from './di/DiIndexData'; import { ModuleIndexData } from './module/ModuleIndexData'; import { AutoloadNamespaceIndexData } from './autoload-namespace/AutoloadNamespaceIndexData'; import { EventsIndexData } from './events/EventsIndexData'; +import Logger from 'util/Logger'; type IndexerInstance = DiIndexer | ModuleIndexer | AutoloadNamespaceIndexer | EventsIndexer; @@ -51,7 +52,7 @@ class IndexManager { ): Promise { const workspaceUri = workspaceFolder.uri; - Common.startStopwatch('indexWorkspace'); + Logger.logWithTime('Indexing workspace', workspaceFolder.name); for (const indexer of this.indexers) { if (!force && !this.shouldIndex(indexer)) { @@ -61,8 +62,7 @@ class IndexManager { const indexData = this.getIndexStorageData(indexer.getId()) || new Map(); - const timer = `indexer_${indexer.getId()}`; - Common.startStopwatch(timer); + Logger.logWithTime('Indexing', indexer.getName()); const files = await workspace.findFiles(indexer.getPattern(workspaceUri), 'dev/**'); let doneCount = 0; @@ -90,16 +90,16 @@ class IndexManager { clear([indexer.getId()]); - Common.stopStopwatch(timer); + Logger.logWithTime('Indexing', indexer.getName(), 'done'); progress.report({ increment: 100 }); } - Common.stopStopwatch('indexWorkspace'); + Logger.logWithTime('Finished indexing workspace', workspaceFolder.name); } public async indexFile(workspaceFolder: WorkspaceFolder, file: Uri): Promise { - Common.startStopwatch('indexFile'); + Logger.logWithTime('Indexing file', file.fsPath); await Promise.all( this.indexers.map(async indexer => { @@ -107,17 +107,17 @@ class IndexManager { }) ); - Common.stopStopwatch('indexFile'); + Logger.logWithTime('Finished indexing file', file.fsPath); } public async indexFiles(workspaceFolder: WorkspaceFolder, files: Uri[]): Promise { - Common.startStopwatch('indexFiles'); + Logger.logWithTime(`Indexing ${files.length} files`); for (const indexer of this.indexers) { await Promise.all(files.map(file => this.indexFileInner(workspaceFolder, file, indexer))); } - Common.stopStopwatch('indexFiles'); + Logger.logWithTime(`Finished indexing ${files.length} files`); } public getIndexStorageData( diff --git a/src/test/extension.test.ts b/src/test/extension.test.ts deleted file mode 100644 index 17e2eab..0000000 --- a/src/test/extension.test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import * as assert from 'assert'; - -// You can import and use all API from the 'vscode' module -// as well as import your extension to test it -import * as vscode from 'vscode'; -// import * as myExtension from '../../extension'; - -suite('Extension Test Suite', () => { - vscode.window.showInformationMessage('Start all tests.'); - - test('Sample test', () => { - assert.strictEqual(-1, [1, 2, 3].indexOf(5)); - assert.strictEqual(-1, [1, 2, 3].indexOf(0)); - }); -}); diff --git a/src/test/generator/block/BlockClassGenerator.test.ts b/src/test/generator/block/BlockClassGenerator.test.ts new file mode 100644 index 0000000..30ca1f6 --- /dev/null +++ b/src/test/generator/block/BlockClassGenerator.test.ts @@ -0,0 +1,95 @@ +import { BlockWizardData } from 'wizard/BlockWizard'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import BlockClassGenerator from 'generator/block/BlockClassGenerator'; +import { describe, it, before, afterEach } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; +import FileHeader from 'common/php/FileHeader'; +import sinon from 'sinon'; + +describe('BlockClassGenerator Tests', () => { + const blockWizardData: BlockWizardData = { + module: 'Foo_Bar', + name: 'TestBlock', + path: 'Block', + }; + + before(async () => { + await setup(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should generate block class file', async () => { + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with test data + const generator = new BlockClassGenerator(blockWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/block/TestBlock.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location', async () => { + // Create the generator with test data + const generator = new BlockClassGenerator(blockWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path + const expectedPath = Uri.joinPath(workspaceUri, 'app/code/Foo/Bar/Block/TestBlock.php').fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate block class in custom path', async () => { + // Create test data with custom path + const customPathData: BlockWizardData = { + ...blockWizardData, + path: 'Block/Custom/Path', + }; + + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with custom path data + const generator = new BlockClassGenerator(customPathData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content for custom path + const referenceContent = getReferenceFile('generator/block/TestBlockCustomPath.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + + // Verify file location + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/Block/Custom/Path/TestBlock.php' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); +}); diff --git a/src/test/generator/module/ModuleComposerGenerator.test.ts b/src/test/generator/module/ModuleComposerGenerator.test.ts new file mode 100644 index 0000000..d84a8d5 --- /dev/null +++ b/src/test/generator/module/ModuleComposerGenerator.test.ts @@ -0,0 +1,42 @@ +import { ModuleWizardComposerData } from 'wizard/ModuleWizard'; +import { License } from 'types'; +import * as assert from 'assert'; +import ModuleComposerGenerator from 'generator/module/ModuleComposerGenerator'; +import { describe, it, before } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; + +describe('ModuleComposerGenerator Tests', () => { + const moduleWizardData: ModuleWizardComposerData = { + vendor: 'Foo', + module: 'Bar', + sequence: [], + license: License.MIT, + version: '1.0.0', + copyright: 'Test Copyright', + composer: true, + composerName: 'foo/bar-module', + composerDescription: 'A test module', + }; + + before(async () => { + await setup(); + }); + + it('should generate composer.json', async () => { + // Create the generator with modified test data + const generator = new ModuleComposerGenerator(moduleWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/module/composer.json'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); +}); diff --git a/src/test/generator/module/ModuleRegistrationGenerator.test.ts b/src/test/generator/module/ModuleRegistrationGenerator.test.ts new file mode 100644 index 0000000..75b8ed3 --- /dev/null +++ b/src/test/generator/module/ModuleRegistrationGenerator.test.ts @@ -0,0 +1,64 @@ +import { ModuleWizardData } from 'wizard/ModuleWizard'; +import { License } from 'types'; +import * as assert from 'assert'; +import ModuleRegistrationGenerator from 'generator/module/ModuleRegistrationGenerator'; +import FileHeader from 'common/php/FileHeader'; +import { describe, it, after, before } from 'mocha'; +import sinon from 'sinon'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; +import { setup } from 'test/setup'; + +describe('ModuleRegistrationGenerator Tests', () => { + const moduleWizardData: ModuleWizardData = { + vendor: 'Foo', + module: 'Bar', + sequence: [], + license: License.None, + version: '1.0.0', + copyright: 'Test Copyright', + composer: false, + }; + + before(async () => { + await setup(); + }); + + after(async () => { + sinon.restore(); + }); + + it('should generate registration.php', async () => { + // Create the generator with test data + const generator = new ModuleRegistrationGenerator(moduleWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the content of the reference file + const referenceContent = getReferenceFile('generator/module/registration.php'); + + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate registration.php with comment', async () => { + // Create the generator with test data + const generator = new ModuleRegistrationGenerator(moduleWizardData); + + // Mock the FileHeader.getHeaderAsComment method to return a test comment + sinon.stub(FileHeader, 'getHeader').returns('This is a test comment'); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the content of the reference file with comments + const referenceContent = getReferenceFile('generator/module/registration-with-comment.php'); + + assert.strictEqual(generatedFile.content, referenceContent); + }); +}); diff --git a/src/test/generator/module/ModuleXmlGenerator.test.ts b/src/test/generator/module/ModuleXmlGenerator.test.ts new file mode 100644 index 0000000..0968406 --- /dev/null +++ b/src/test/generator/module/ModuleXmlGenerator.test.ts @@ -0,0 +1,85 @@ +import { ModuleWizardData } from 'wizard/ModuleWizard'; +import { License } from 'types'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import ModuleXmlGenerator from 'generator/module/ModuleXmlGenerator'; +import { describe, it, before, afterEach } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; +import sinon from 'sinon'; + +describe('ModuleXmlGenerator Tests', () => { + const moduleWizardData: ModuleWizardData = { + vendor: 'Foo', + module: 'Bar', + sequence: [], + license: License.None, + version: '1.0.0', + copyright: 'Test Copyright', + composer: false, + }; + + before(async () => { + await setup(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should generate module.xml', async () => { + // Create the generator with test data + const generator = new ModuleXmlGenerator(moduleWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/module/module.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location', async () => { + // Create the generator with test data + const generator = new ModuleXmlGenerator(moduleWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path + const expectedPath = Uri.joinPath(workspaceUri, 'app/code/Foo/Bar/etc/module.xml').fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate module.xml with sequence', async () => { + // Create test data with sequence + const dataWithSequence: ModuleWizardData = { + ...moduleWizardData, + sequence: ['Magento_Catalog', 'Magento_Customer'], + }; + + // Create the generator with sequence data + const generator = new ModuleXmlGenerator(dataWithSequence); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/module/module-with-sequence.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); +}); diff --git a/src/test/generator/observer/ObserverClassGenerator.test.ts b/src/test/generator/observer/ObserverClassGenerator.test.ts new file mode 100644 index 0000000..6d27be9 --- /dev/null +++ b/src/test/generator/observer/ObserverClassGenerator.test.ts @@ -0,0 +1,102 @@ +import { ObserverWizardData } from 'wizard/ObserverWizard'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import ObserverClassGenerator from 'generator/observer/ObserverClassGenerator'; +import { describe, it, before, afterEach } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; +import FileHeader from 'common/php/FileHeader'; +import sinon from 'sinon'; +import { MagentoScope } from 'types'; + +describe('ObserverClassGenerator Tests', () => { + const observerWizardData: ObserverWizardData = { + module: 'Foo_Bar', + className: 'TestObserver', + directoryPath: 'Observer', + eventName: 'test_event', + observerName: 'test_observer', + area: MagentoScope.Frontend, + }; + + before(async () => { + await setup(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should generate observer class file', async () => { + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with test data + const generator = new ObserverClassGenerator(observerWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/observer/TestObserver.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location', async () => { + // Create the generator with test data + const generator = new ObserverClassGenerator(observerWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/Observer/TestObserver.php' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate observer in custom path', async () => { + // Create test data with custom path + const customPathData: ObserverWizardData = { + ...observerWizardData, + directoryPath: 'Observer/Custom/Path', + }; + + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with custom path data + const generator = new ObserverClassGenerator(customPathData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/observer/TestObserverCustomPath.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + + // Verify file location + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/Observer/Custom/Path/TestObserver.php' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); +}); diff --git a/src/test/generator/observer/ObserverEventsGenerator.test.ts b/src/test/generator/observer/ObserverEventsGenerator.test.ts new file mode 100644 index 0000000..f8c19ae --- /dev/null +++ b/src/test/generator/observer/ObserverEventsGenerator.test.ts @@ -0,0 +1,116 @@ +import { ObserverWizardData } from 'wizard/ObserverWizard'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import ObserverEventsGenerator from 'generator/observer/ObserverEventsGenerator'; +import { describe, it, before, afterEach } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; +import { MagentoScope } from 'types'; +import FileHeader from 'common/xml/FileHeader'; +import sinon from 'sinon'; + +describe('ObserverEventsGenerator Tests', () => { + const observerWizardData: ObserverWizardData = { + module: 'Foo_Bar', + className: 'TestObserver', + directoryPath: 'Observer', + eventName: 'test_event', + observerName: 'test_observer', + area: MagentoScope.Frontend, + }; + + before(async () => { + await setup(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should generate events.xml', async () => { + // Create the generator with test data + const generator = new ObserverEventsGenerator(observerWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/observer/events.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location', async () => { + // Create the generator with test data + const generator = new ObserverEventsGenerator(observerWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/etc/frontend/events.xml' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate events.xml in adminhtml area', async () => { + // Create test data with adminhtml area + const adminhtmlData: ObserverWizardData = { + ...observerWizardData, + area: MagentoScope.Adminhtml, + }; + + // Create the generator with adminhtml data + const generator = new ObserverEventsGenerator(adminhtmlData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/observer/events-adminhtml.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + + // Verify file location + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/etc/adminhtml/events.xml' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate events.xml with comment', async () => { + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns(''); + + // Create the generator with test data + const generator = new ObserverEventsGenerator(observerWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/observer/events-with-comment.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); +}); diff --git a/src/test/generator/plugin/PluginClassGenerator.test.ts b/src/test/generator/plugin/PluginClassGenerator.test.ts new file mode 100644 index 0000000..3e02f35 --- /dev/null +++ b/src/test/generator/plugin/PluginClassGenerator.test.ts @@ -0,0 +1,115 @@ +import { PluginContextWizardData } from 'wizard/PluginContextWizard'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import PluginClassGenerator from 'generator/plugin/PluginClassGenerator'; +import { describe, it, before, afterEach } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getReferenceFilePath, getTestWorkspaceUri } from 'test/util'; +import FileHeader from 'common/php/FileHeader'; +import sinon from 'sinon'; +import { PhpClass } from 'parser/php/PhpClass'; +import { PhpMethod } from 'parser/php/PhpMethod'; +import { MagentoScope } from 'types'; +import PhpParser from 'parser/php/Parser'; + +describe('PluginClassGenerator Tests', () => { + const pluginWizardData: PluginContextWizardData = { + module: 'Foo_Bar', + className: 'TestPlugin', + name: 'test_plugin', + type: 'around', + method: 'setData', + sortOrder: 10, + scope: MagentoScope.Global, + }; + + let subjectClass: PhpClass; + let subjectMethod: PhpMethod; + + before(async () => { + await setup(); + + const parser = new PhpParser(); + const referenceFilePath = getReferenceFilePath('generator/plugin/SubjectClass.php'); + const phpFile = await parser.parse(Uri.file(referenceFilePath)); + subjectClass = phpFile.classes[0]; + subjectMethod = subjectClass.methods[0]; + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should generate plugin class file', async () => { + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with test data + const generator = new PluginClassGenerator(pluginWizardData, subjectClass, subjectMethod); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/plugin/TestPlugin.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location', async () => { + // Create the generator with test data + const generator = new PluginClassGenerator(pluginWizardData, subjectClass, subjectMethod); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/Plugin/TestPlugin.php' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate plugin in custom path', async () => { + // Create test data with custom path + const customPathData: PluginContextWizardData = { + ...pluginWizardData, + className: 'Custom/Path/TestPlugin', + }; + + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with custom path data + const generator = new PluginClassGenerator(customPathData, subjectClass, subjectMethod); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/plugin/TestPluginCustomPath.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + + // Verify file location + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/Plugin/Custom/Path/TestPlugin.php' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); +}); diff --git a/src/test/generator/plugin/PluginDiGenerator.test.ts b/src/test/generator/plugin/PluginDiGenerator.test.ts new file mode 100644 index 0000000..0efeb53 --- /dev/null +++ b/src/test/generator/plugin/PluginDiGenerator.test.ts @@ -0,0 +1,97 @@ +import { PluginContextWizardData } from 'wizard/PluginContextWizard'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import PluginDiGenerator from 'generator/plugin/PluginDiGenerator'; +import { describe, it, before } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getReferenceFilePath, getTestWorkspaceUri } from 'test/util'; +import { MagentoScope } from 'types'; +import { PhpClass } from 'parser/php/PhpClass'; +import PhpParser from 'parser/php/Parser'; +import { PhpMethod } from 'parser/php/PhpMethod'; + +describe('PluginDiGenerator Tests', () => { + const pluginWizardData: PluginContextWizardData = { + module: 'Foo_Bar', + className: 'TestPlugin', + name: 'test_plugin', + type: 'around', + method: 'setData', + sortOrder: 10, + scope: MagentoScope.Global, + }; + + let subjectClass: PhpClass; + let subjectMethod: PhpMethod; + + before(async () => { + await setup(); + + const parser = new PhpParser(); + const referenceFilePath = getReferenceFilePath('generator/plugin/SubjectClass.php'); + const phpFile = await parser.parse(Uri.file(referenceFilePath)); + subjectClass = phpFile.classes[0]; + subjectMethod = subjectClass.methods[0]; + }); + + it('should generate di.xml', async () => { + // Create the generator with test data + const generator = new PluginDiGenerator(pluginWizardData, subjectClass, subjectMethod); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/plugin/di.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location', async () => { + // Create the generator with test data + const generator = new PluginDiGenerator(pluginWizardData, subjectClass, subjectMethod); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path + const expectedPath = Uri.joinPath(workspaceUri, 'app/code/Foo/Bar/etc/di.xml').fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate di.xml in adminhtml area', async () => { + // Create test data with adminhtml area + const adminhtmlData: PluginContextWizardData = { + ...pluginWizardData, + scope: MagentoScope.Adminhtml, + }; + + // Create the generator with adminhtml data + const generator = new PluginDiGenerator(adminhtmlData, subjectClass, subjectMethod); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/plugin/di-adminhtml.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + + // Verify file location + const expectedPath = Uri.joinPath(workspaceUri, 'app/code/Foo/Bar/etc/adminhtml/di.xml').fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); +}); diff --git a/src/test/generator/preference/PreferenceClassGenerator.test.ts b/src/test/generator/preference/PreferenceClassGenerator.test.ts new file mode 100644 index 0000000..d29814e --- /dev/null +++ b/src/test/generator/preference/PreferenceClassGenerator.test.ts @@ -0,0 +1,94 @@ +import { PreferenceWizardData } from 'wizard/PreferenceWizard'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import PreferenceClassGenerator from 'generator/preference/PreferenceClassGenerator'; +import { describe, it, before, afterEach } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; +import FileHeader from 'common/php/FileHeader'; +import sinon from 'sinon'; +import { MagentoScope } from 'types'; + +describe('PreferenceClassGenerator Tests', () => { + const preferenceWizardData: PreferenceWizardData = { + module: 'Foo_Bar', + className: 'TestPreference', + directory: 'Model', + parentClass: 'Magento\\Catalog\\Model\\Product', + inheritClass: true, + area: MagentoScope.Global, + }; + + before(async () => { + await setup(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should generate preference class file', async () => { + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with test data + const generator = new PreferenceClassGenerator(preferenceWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/preference/TestPreference.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location', async () => { + // Create the generator with test data + const generator = new PreferenceClassGenerator(preferenceWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path + const expectedPath = Uri.joinPath( + workspaceUri, + 'app/code/Foo/Bar/Model/TestPreference.php' + ).fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate preference without inheritance', async () => { + // Create test data without inheritance + const noInheritanceData: PreferenceWizardData = { + ...preferenceWizardData, + inheritClass: false, + }; + + // Mock the FileHeader.getHeader method to return a consistent header + sinon.stub(FileHeader, 'getHeader').returns('Foo_Bar'); + + // Create the generator with modified data + const generator = new PreferenceClassGenerator(noInheritanceData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/preference/TestPreferenceNoInherit.php'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); +}); diff --git a/src/test/generator/preference/PreferenceDiGenerator.test.ts b/src/test/generator/preference/PreferenceDiGenerator.test.ts new file mode 100644 index 0000000..a14b7f9 --- /dev/null +++ b/src/test/generator/preference/PreferenceDiGenerator.test.ts @@ -0,0 +1,105 @@ +import { PreferenceWizardData } from 'wizard/PreferenceWizard'; +import * as assert from 'assert'; +import { Uri } from 'vscode'; +import PreferenceDiGenerator from 'generator/preference/PreferenceDiGenerator'; +import { describe, it, before, afterEach } from 'mocha'; +import { setup } from 'test/setup'; +import { getReferenceFile, getTestWorkspaceUri } from 'test/util'; +import sinon from 'sinon'; +import { MagentoScope } from 'types'; + +describe('PreferenceDiGenerator Tests', () => { + const preferenceWizardData: PreferenceWizardData = { + module: 'Foo_Bar', + className: 'TestPreference', + directory: 'Model', + parentClass: 'Magento\\Catalog\\Model\\Product', + inheritClass: true, + area: MagentoScope.Global, + }; + + before(async () => { + await setup(); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should generate di.xml file', async () => { + // Create the generator with test data + const generator = new PreferenceDiGenerator(preferenceWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Get the reference file content + const referenceContent = getReferenceFile('generator/preference/di.xml'); + + // Compare the generated content with reference + assert.strictEqual(generatedFile.content, referenceContent); + }); + + it('should generate file in correct location for global scope', async () => { + // Create the generator with test data + const generator = new PreferenceDiGenerator(preferenceWizardData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path for global scope + const expectedPath = Uri.joinPath(workspaceUri, 'app/code/Foo/Bar/etc/di.xml').fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate file in correct location for frontend scope', async () => { + // Create test data with frontend scope + const frontendData: PreferenceWizardData = { + ...preferenceWizardData, + area: MagentoScope.Frontend, + }; + + // Create the generator with frontend data + const generator = new PreferenceDiGenerator(frontendData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path for frontend scope + const expectedPath = Uri.joinPath(workspaceUri, 'app/code/Foo/Bar/etc/frontend/di.xml').fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); + + it('should generate file in correct location for adminhtml scope', async () => { + // Create test data with adminhtml scope + const adminhtmlData: PreferenceWizardData = { + ...preferenceWizardData, + area: MagentoScope.Adminhtml, + }; + + // Create the generator with adminhtml data + const generator = new PreferenceDiGenerator(adminhtmlData); + + // Use a test workspace URI + const workspaceUri = getTestWorkspaceUri(); + + // Generate the file + const generatedFile = await generator.generate(workspaceUri); + + // Expected path for adminhtml scope + const expectedPath = Uri.joinPath(workspaceUri, 'app/code/Foo/Bar/etc/adminhtml/di.xml').fsPath; + + assert.strictEqual(generatedFile.uri.fsPath, expectedPath); + }); +}); diff --git a/src/test/setup.ts b/src/test/setup.ts new file mode 100644 index 0000000..b546ae8 --- /dev/null +++ b/src/test/setup.ts @@ -0,0 +1,10 @@ +import ExtensionState from 'common/ExtensionState'; +import { extensions } from 'vscode'; +import Common from 'util/Common'; + +export async function setup() { + const extension = extensions.getExtension(Common.EXTENSION_ID); + const context = await extension?.activate(); + + ExtensionState.init(context, []); +} diff --git a/src/test/util.ts b/src/test/util.ts new file mode 100644 index 0000000..a44ec59 --- /dev/null +++ b/src/test/util.ts @@ -0,0 +1,18 @@ +import FileSystem from 'util/FileSystem'; +import fs from 'fs'; +import path from 'path'; +import { Uri } from 'vscode'; + +export function getReferenceFilePath(filePath: string) { + const resourcePath = FileSystem.getExtensionPath('test-resources'); + return path.resolve(resourcePath, 'reference', filePath); +} + +export function getReferenceFile(filePath: string) { + const refFilePath = getReferenceFilePath(filePath); + return fs.readFileSync(refFilePath, 'utf8'); +} + +export function getTestWorkspaceUri() { + return Uri.file(FileSystem.getExtensionPath('test-resources/workspace')); +} diff --git a/src/util/Common.ts b/src/util/Common.ts index 657b95b..94a7bab 100644 --- a/src/util/Common.ts +++ b/src/util/Common.ts @@ -2,31 +2,7 @@ import ExtensionState from 'common/ExtensionState'; import { workspace, WorkspaceFolder, window } from 'vscode'; export default class Common { - private static isDev = process.env.NODE_ENV !== 'production'; - - public static startStopwatch(name: string) { - if (!this.isDev) { - return; - } - - console.time(name); - } - - public static stopStopwatch(name: string) { - if (!this.isDev) { - return; - } - - console.timeEnd(name); - } - - public static log(...message: string[]) { - if (!this.isDev) { - return; - } - - console.log(...message); - } + public static EXTENSION_ID = 'magebit.magebit-magento-toolbox'; public static getActiveWorkspaceFolder(): WorkspaceFolder | undefined { if (!workspace.workspaceFolders) { diff --git a/src/util/FileSystem.ts b/src/util/FileSystem.ts index a522a77..7480cf2 100644 --- a/src/util/FileSystem.ts +++ b/src/util/FileSystem.ts @@ -1,4 +1,6 @@ import { Uri, workspace } from 'vscode'; +import * as path from 'path'; +import ExtensionState from 'common/ExtensionState'; export default class FileSystem { public static async fileExists(uri: Uri): Promise { @@ -21,4 +23,9 @@ export default class FileSystem { public static async writeFile(uri: Uri, content: string): Promise { await workspace.fs.writeFile(uri, Buffer.from(content)); } + + public static getExtensionPath(dir: string): string { + ExtensionState.context.extensionPath; + return path.join(ExtensionState.context.extensionPath, 'dist', dir); + } } diff --git a/src/util/Logger.ts b/src/util/Logger.ts new file mode 100644 index 0000000..09bfd25 --- /dev/null +++ b/src/util/Logger.ts @@ -0,0 +1,15 @@ +import { window } from 'vscode'; + +export class Logger { + private channel = window.createOutputChannel('Magento Toolbox'); + + public log(...message: string[]) { + this.channel.appendLine(message.join(' ')); + } + + public logWithTime(...message: string[]) { + this.log(new Date().toISOString(), ...message); + } +} + +export default new Logger(); diff --git a/src/util/Magento.ts b/src/util/Magento.ts index 7fc5036..183e573 100644 --- a/src/util/Magento.ts +++ b/src/util/Magento.ts @@ -3,6 +3,7 @@ import lowerFirst from 'lodash-es/lowerFirst'; import { MagentoScope } from 'types'; import { Uri, WorkspaceFolder } from 'vscode'; import FileSystem from './FileSystem'; + export default class Magento { public static isPluginMethod(method: string) { return /^around|^before|^after/.test(method); diff --git a/src/webview/GeneratorWizard.ts b/src/webview/GeneratorWizard.ts index 66985e2..fc7b5d9 100644 --- a/src/webview/GeneratorWizard.ts +++ b/src/webview/GeneratorWizard.ts @@ -49,6 +49,8 @@ export class GeneratorWizard extends Webview { if (!loaded) { this.panel?.dispose(); + console.error('Failed to load wizard', pageData); + reject(new Error('Failed to load wizard')); } }, 5000); diff --git a/src/webview/components/App.tsx b/src/webview/components/App.tsx index 0433780..a69a1f6 100644 --- a/src/webview/components/App.tsx +++ b/src/webview/components/App.tsx @@ -19,7 +19,6 @@ const App: React.FC = () => { setPage(Page.Wizard); setPageData(message.data); - console.log(message.data); break; } }); diff --git a/src/webview/components/Wizard/Renderer.tsx b/src/webview/components/Wizard/Renderer.tsx index 5837012..0d67e7f 100644 --- a/src/webview/components/Wizard/Renderer.tsx +++ b/src/webview/components/Wizard/Renderer.tsx @@ -1,4 +1,4 @@ -import { Form, Formik, FormikProps, FormikValues } from 'formik'; +import { Formik, FormikProps, FormikValues } from 'formik'; import { useCallback } from 'react'; import { WebviewApi } from 'vscode-webview'; import Validator from 'validatorjs'; diff --git a/templates/php/registration.ejs b/templates/php/registration.ejs index aefe240..8a72226 100644 --- a/templates/php/registration.ejs +++ b/templates/php/registration.ejs @@ -1,6 +1,7 @@ -<%- fileHeader -%> +<%- fileHeader %> <% } -%> declare(strict_types=1); diff --git a/test-resources/reference/generator/block/TestBlock.php b/test-resources/reference/generator/block/TestBlock.php new file mode 100644 index 0000000..cdecba5 --- /dev/null +++ b/test-resources/reference/generator/block/TestBlock.php @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/test-resources/reference/generator/module/module-with-sequence.xml b/test-resources/reference/generator/module/module-with-sequence.xml new file mode 100644 index 0000000..9450bcd --- /dev/null +++ b/test-resources/reference/generator/module/module-with-sequence.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test-resources/reference/generator/module/module.xml b/test-resources/reference/generator/module/module.xml new file mode 100644 index 0000000..22316b9 --- /dev/null +++ b/test-resources/reference/generator/module/module.xml @@ -0,0 +1,4 @@ + + + + diff --git a/test-resources/reference/generator/module/registration-with-comment.php b/test-resources/reference/generator/module/registration-with-comment.php new file mode 100644 index 0000000..92999a0 --- /dev/null +++ b/test-resources/reference/generator/module/registration-with-comment.php @@ -0,0 +1,11 @@ +getEvent(); + // TODO: Observer code + } +} diff --git a/test-resources/reference/generator/observer/TestObserverCustomPath.php b/test-resources/reference/generator/observer/TestObserverCustomPath.php new file mode 100644 index 0000000..151de11 --- /dev/null +++ b/test-resources/reference/generator/observer/TestObserverCustomPath.php @@ -0,0 +1,27 @@ +getEvent(); + // TODO: Observer code + } +} diff --git a/test-resources/reference/generator/observer/events-adminhtml.xml b/test-resources/reference/generator/observer/events-adminhtml.xml new file mode 100644 index 0000000..96fe3a6 --- /dev/null +++ b/test-resources/reference/generator/observer/events-adminhtml.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/test-resources/reference/generator/observer/events-with-comment.xml b/test-resources/reference/generator/observer/events-with-comment.xml new file mode 100644 index 0000000..867ae2d --- /dev/null +++ b/test-resources/reference/generator/observer/events-with-comment.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/test-resources/reference/generator/observer/events.xml b/test-resources/reference/generator/observer/events.xml new file mode 100644 index 0000000..96fe3a6 --- /dev/null +++ b/test-resources/reference/generator/observer/events.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/test-resources/reference/generator/plugin/SubjectClass.php b/test-resources/reference/generator/plugin/SubjectClass.php new file mode 100644 index 0000000..a83bd8b --- /dev/null +++ b/test-resources/reference/generator/plugin/SubjectClass.php @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/test-resources/reference/generator/plugin/di.xml b/test-resources/reference/generator/plugin/di.xml new file mode 100644 index 0000000..6357502 --- /dev/null +++ b/test-resources/reference/generator/plugin/di.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/test-resources/reference/generator/preference/TestPreference.php b/test-resources/reference/generator/preference/TestPreference.php new file mode 100644 index 0000000..977395c --- /dev/null +++ b/test-resources/reference/generator/preference/TestPreference.php @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/test-resources/workspace/app/code/Foo/Bar/etc/module.xml b/test-resources/workspace/app/code/Foo/Bar/etc/module.xml new file mode 100644 index 0000000..22316b9 --- /dev/null +++ b/test-resources/workspace/app/code/Foo/Bar/etc/module.xml @@ -0,0 +1,4 @@ + + + + diff --git a/test-resources/workspace/app/code/Foo/Bar/registration.php b/test-resources/workspace/app/code/Foo/Bar/registration.php new file mode 100644 index 0000000..dbd30d1 --- /dev/null +++ b/test-resources/workspace/app/code/Foo/Bar/registration.php @@ -0,0 +1,11 @@ + [ + 'Magento_Store' => 1, + 'Magento_Config' => 1, + 'Magento_AdminAnalytics' => 1, + 'Magento_AdminNotification' => 1, + 'Magento_AdobeIms' => 1, + 'Magento_AdobeImsApi' => 1, + 'Magento_AdobeStockAdminUi' => 1, + 'Magento_MediaGallery' => 1, + 'Magento_AdobeStockAssetApi' => 1, + 'Magento_AdobeStockClient' => 1, + 'Magento_AdobeStockClientApi' => 1, + 'Magento_AdobeStockImage' => 1, + 'Magento_Directory' => 1, + 'Magento_AdobeStockImageApi' => 1, + 'Magento_AdvancedPricingImportExport' => 1, + 'Magento_Theme' => 1, + 'Magento_Amqp' => 1, + 'Magento_Backend' => 1, + 'Magento_User' => 1, + 'Magento_Authorization' => 1, + 'Magento_Eav' => 1, + 'Magento_Customer' => 1, + 'Magento_AdminAdobeIms' => 1, + 'Magento_Backup' => 1, + 'Magento_Indexer' => 1, + 'Magento_GraphQl' => 1, + 'Magento_BundleImportExport' => 1, + 'Magento_CacheInvalidate' => 1, + 'Magento_Variable' => 1, + 'Magento_Cms' => 1, + 'Magento_Rule' => 1, + 'Magento_Security' => 1, + 'Magento_CmsGraphQl' => 1, + 'Magento_EavGraphQl' => 1, + 'Magento_Search' => 1, + 'Magento_CatalogImportExport' => 1, + 'Magento_Catalog' => 1, + 'Magento_CatalogInventory' => 1, + 'Magento_CatalogPageBuilderAnalytics' => 1, + 'Magento_CatalogRule' => 1, + 'Magento_Msrp' => 1, + 'Magento_CatalogRuleGraphQl' => 1, + 'Magento_CatalogSearch' => 1, + 'Magento_CatalogUrlRewrite' => 1, + 'Magento_StoreGraphQl' => 1, + 'Magento_MediaStorage' => 1, + 'Magento_Quote' => 1, + 'Magento_SalesSequence' => 1, + 'Magento_CheckoutAgreementsGraphQl' => 1, + 'Magento_MediaGalleryUi' => 1, + 'Magento_CatalogGraphQl' => 1, + 'Magento_CmsPageBuilderAnalytics' => 1, + 'Magento_CmsUrlRewrite' => 1, + 'Magento_CmsUrlRewriteGraphQl' => 1, + 'Magento_CompareListGraphQl' => 1, + 'Magento_Integration' => 1, + 'Magento_Payment' => 1, + 'Magento_Sales' => 1, + 'Magento_QuoteGraphQl' => 1, + 'Magento_Checkout' => 1, + 'Magento_Contact' => 1, + 'Magento_Cookie' => 1, + 'Magento_Cron' => 1, + 'Magento_Csp' => 1, + 'Magento_Widget' => 1, + 'Magento_Robots' => 1, + 'Magento_Analytics' => 1, + 'Magento_Downloadable' => 1, + 'Magento_CustomerGraphQl' => 1, + 'Magento_CustomerImportExport' => 1, + 'Magento_Deploy' => 1, + 'Magento_Developer' => 1, + 'Magento_Dhl' => 1, + 'Magento_AdvancedSearch' => 1, + 'Magento_DirectoryGraphQl' => 1, + 'Magento_DownloadableGraphQl' => 1, + 'Magento_CustomerDownloadableGraphQl' => 1, + 'Magento_ImportExport' => 1, + 'Magento_Bundle' => 1, + 'Magento_CatalogCustomerGraphQl' => 1, + 'Magento_Elasticsearch' => 1, + 'Magento_Elasticsearch7' => 1, + 'Magento_Email' => 1, + 'Magento_EncryptionKey' => 1, + 'Magento_Fedex' => 1, + 'Magento_GiftMessage' => 1, + 'Magento_GiftMessageGraphQl' => 1, + 'Magento_GoogleAdwords' => 1, + 'Magento_GoogleAnalytics' => 1, + 'Magento_GoogleGtag' => 1, + 'Magento_Ui' => 1, + 'Magento_GoogleShoppingAds' => 1, + 'Magento_BundleGraphQl' => 1, + 'Magento_PageCache' => 1, + 'Magento_GroupedProduct' => 1, + 'Magento_GroupedImportExport' => 1, + 'Magento_GroupedCatalogInventory' => 1, + 'Magento_GroupedProductGraphQl' => 1, + 'Magento_DownloadableImportExport' => 1, + 'Magento_Captcha' => 1, + 'Magento_InstantPurchase' => 1, + 'Magento_CatalogAnalytics' => 1, + 'Magento_Inventory' => 1, + 'Magento_InventoryAdminUi' => 1, + 'Magento_InventoryAdvancedCheckout' => 1, + 'Magento_InventoryApi' => 1, + 'Magento_InventoryBundleImportExport' => 1, + 'Magento_InventoryBundleProduct' => 1, + 'Magento_InventoryBundleProductAdminUi' => 1, + 'Magento_InventoryBundleProductIndexer' => 1, + 'Magento_InventoryCatalog' => 1, + 'Magento_InventorySales' => 1, + 'Magento_InventoryCatalogAdminUi' => 1, + 'Magento_InventoryCatalogApi' => 1, + 'Magento_InventoryCatalogFrontendUi' => 1, + 'Magento_InventoryCatalogSearch' => 1, + 'Magento_InventoryCatalogSearchBundleProduct' => 1, + 'Magento_InventoryCatalogSearchConfigurableProduct' => 1, + 'Magento_ConfigurableProduct' => 1, + 'Magento_ConfigurableProductGraphQl' => 1, + 'Magento_InventoryConfigurableProduct' => 1, + 'Magento_InventoryConfigurableProductIndexer' => 1, + 'Magento_InventoryConfiguration' => 1, + 'Magento_InventoryConfigurationApi' => 1, + 'Magento_InventoryDistanceBasedSourceSelection' => 1, + 'Magento_InventoryDistanceBasedSourceSelectionAdminUi' => 1, + 'Magento_InventoryDistanceBasedSourceSelectionApi' => 1, + 'Magento_InventoryElasticsearch' => 1, + 'Magento_InventoryExportStockApi' => 1, + 'Magento_InventoryIndexer' => 1, + 'Magento_InventorySalesApi' => 1, + 'Magento_InventoryGroupedProduct' => 1, + 'Magento_InventoryGroupedProductAdminUi' => 1, + 'Magento_InventoryGroupedProductIndexer' => 1, + 'Magento_InventoryImportExport' => 1, + 'Magento_InventoryInStorePickupApi' => 1, + 'Magento_InventoryInStorePickupAdminUi' => 1, + 'Magento_InventorySourceSelectionApi' => 1, + 'Magento_InventoryInStorePickup' => 1, + 'Magento_InventoryInStorePickupGraphQl' => 1, + 'Magento_Shipping' => 1, + 'Magento_InventoryInStorePickupShippingApi' => 1, + 'Magento_InventoryInStorePickupQuoteGraphQl' => 1, + 'Magento_InventoryInStorePickupSales' => 1, + 'Magento_InventoryInStorePickupSalesApi' => 1, + 'Magento_InventoryInStorePickupQuote' => 1, + 'Magento_InventoryInStorePickupShipping' => 1, + 'Magento_InventoryInStorePickupShippingAdminUi' => 1, + 'Magento_Multishipping' => 1, + 'Magento_Webapi' => 1, + 'Magento_InventoryCache' => 1, + 'Magento_InventoryLowQuantityNotification' => 1, + 'Magento_Reports' => 1, + 'Magento_InventoryLowQuantityNotificationApi' => 1, + 'Magento_InventoryMultiDimensionalIndexerApi' => 1, + 'Magento_InventoryProductAlert' => 1, + 'Magento_InventoryQuoteGraphQl' => 1, + 'Magento_InventoryRequisitionList' => 1, + 'Magento_InventoryReservations' => 1, + 'Magento_InventoryReservationCli' => 1, + 'Magento_InventoryReservationsApi' => 1, + 'Magento_InventoryExportStock' => 1, + 'Magento_InventorySalesAdminUi' => 1, + 'Magento_CatalogInventoryGraphQl' => 1, + 'Magento_InventorySalesAsyncOrder' => 1, + 'Magento_InventorySalesFrontendUi' => 1, + 'Magento_InventorySetupFixtureGenerator' => 1, + 'Magento_InventoryShipping' => 1, + 'Magento_InventoryShippingAdminUi' => 1, + 'Magento_InventorySourceDeductionApi' => 1, + 'Magento_InventorySourceSelection' => 1, + 'Magento_InventoryInStorePickupFrontend' => 1, + 'Magento_InventorySwatchesFrontendUi' => 1, + 'Magento_InventoryVisualMerchandiser' => 1, + 'Magento_InventoryWishlist' => 1, + 'Magento_JwtFrameworkAdapter' => 1, + 'Magento_JwtUserToken' => 1, + 'Magento_LayeredNavigation' => 1, + 'Magento_LoginAsCustomer' => 1, + 'Magento_LoginAsCustomerAdminUi' => 1, + 'Magento_LoginAsCustomerApi' => 1, + 'Magento_LoginAsCustomerAssistance' => 1, + 'Magento_LoginAsCustomerFrontendUi' => 1, + 'Magento_LoginAsCustomerGraphQl' => 1, + 'Magento_LoginAsCustomerLog' => 1, + 'Magento_LoginAsCustomerPageCache' => 1, + 'Magento_LoginAsCustomerQuote' => 1, + 'Magento_LoginAsCustomerSales' => 1, + 'Magento_Marketplace' => 1, + 'Magento_MediaContent' => 1, + 'Magento_MediaContentApi' => 1, + 'Magento_MediaContentCatalog' => 1, + 'Magento_MediaContentCms' => 1, + 'Magento_MediaContentSynchronization' => 1, + 'Magento_MediaContentSynchronizationApi' => 1, + 'Magento_MediaContentSynchronizationCatalog' => 1, + 'Magento_MediaContentSynchronizationCms' => 1, + 'Magento_AdobeStockAsset' => 1, + 'Magento_MediaGalleryApi' => 1, + 'Magento_MediaGalleryCatalog' => 1, + 'Magento_MediaGalleryCatalogIntegration' => 1, + 'Magento_MediaGalleryCatalogUi' => 1, + 'Magento_MediaGalleryCmsUi' => 1, + 'Magento_MediaGalleryIntegration' => 1, + 'Magento_MediaGalleryMetadata' => 1, + 'Magento_MediaGalleryMetadataApi' => 1, + 'Magento_MediaGalleryRenditions' => 1, + 'Magento_MediaGalleryRenditionsApi' => 1, + 'Magento_MediaGallerySynchronization' => 1, + 'Magento_MediaGallerySynchronizationApi' => 1, + 'Magento_MediaGallerySynchronizationMetadata' => 1, + 'Magento_AdobeStockImageAdminUi' => 1, + 'Magento_MediaGalleryUiApi' => 1, + 'Magento_CatalogWidget' => 1, + 'Magento_MessageQueue' => 1, + 'Magento_ConfigurableImportExport' => 1, + 'Magento_MsrpConfigurableProduct' => 1, + 'Magento_MsrpGroupedProduct' => 1, + 'Magento_InventoryInStorePickupMultishipping' => 1, + 'Magento_MysqlMq' => 1, + 'Magento_NewRelicReporting' => 1, + 'Magento_Newsletter' => 1, + 'Magento_NewsletterGraphQl' => 1, + 'Magento_OfflinePayments' => 1, + 'Magento_SalesRule' => 1, + 'Magento_OpenSearch' => 1, + 'Magento_Sitemap' => 1, + 'Magento_PageBuilder' => 1, + 'Magento_PageBuilderAnalytics' => 1, + 'Magento_GraphQlCache' => 1, + 'Magento_CardinalCommerce' => 1, + 'Magento_PaymentGraphQl' => 1, + 'Magento_Vault' => 1, + 'Magento_Paypal' => 1, + 'Magento_PaypalGraphQl' => 1, + 'Magento_Persistent' => 1, + 'Magento_ProductAlert' => 1, + 'Magento_ProductVideo' => 1, + 'Magento_CheckoutAgreements' => 1, + 'Magento_QuoteAnalytics' => 1, + 'Magento_QuoteBundleOptions' => 1, + 'Magento_QuoteConfigurableOptions' => 1, + 'Magento_QuoteDownloadableLinks' => 1, + 'Magento_InventoryConfigurableProductAdminUi' => 1, + 'Magento_ReCaptchaAdminUi' => 1, + 'Magento_ReCaptchaCheckout' => 1, + 'Magento_ReCaptchaCheckoutSalesRule' => 1, + 'Magento_ReCaptchaContact' => 1, + 'Magento_ReCaptchaCustomer' => 1, + 'Magento_ReCaptchaFrontendUi' => 1, + 'Magento_ReCaptchaMigration' => 1, + 'Magento_ReCaptchaNewsletter' => 1, + 'Magento_ReCaptchaPaypal' => 1, + 'Magento_ReCaptchaReview' => 1, + 'Magento_ReCaptchaSendFriend' => 1, + 'Magento_ReCaptchaStorePickup' => 1, + 'Magento_ReCaptchaUi' => 1, + 'Magento_ReCaptchaUser' => 1, + 'Magento_ReCaptchaValidation' => 1, + 'Magento_ReCaptchaValidationApi' => 1, + 'Magento_ReCaptchaVersion2Checkbox' => 1, + 'Magento_ReCaptchaVersion2Invisible' => 1, + 'Magento_ReCaptchaVersion3Invisible' => 1, + 'Magento_ReCaptchaWebapiApi' => 1, + 'Magento_ReCaptchaWebapiGraphQl' => 1, + 'Magento_ReCaptchaWebapiRest' => 1, + 'Magento_ReCaptchaWebapiUi' => 1, + 'Magento_RelatedProductGraphQl' => 1, + 'Magento_ReleaseNotification' => 1, + 'Magento_RemoteStorage' => 1, + 'Magento_InventoryLowQuantityNotificationAdminUi' => 1, + 'Magento_RequireJs' => 1, + 'Magento_Review' => 1, + 'Magento_ReviewAnalytics' => 1, + 'Magento_ReviewGraphQl' => 1, + 'Magento_AwsS3' => 1, + 'Magento_Rss' => 1, + 'Magento_PageBuilderAdminAnalytics' => 1, + 'Magento_CatalogRuleConfigurable' => 1, + 'Magento_SalesAnalytics' => 1, + 'Magento_SalesGraphQl' => 1, + 'Magento_SalesInventory' => 1, + 'Magento_OfflineShipping' => 1, + 'Magento_ConfigurableProductSales' => 1, + 'Magento_UrlRewrite' => 1, + 'Magento_UrlRewriteGraphQl' => 1, + 'Magento_CustomerAnalytics' => 1, + 'Magento_Securitytxt' => 1, + 'Magento_SendFriend' => 1, + 'Magento_SendFriendGraphQl' => 1, + 'Magento_InventoryInStorePickupSalesAdminUi' => 1, + 'Magento_AwsS3PageBuilder' => 1, + 'Magento_InventoryGraphQl' => 1, + 'Magento_CatalogCmsGraphQl' => 1, + 'Magento_Swagger' => 1, + 'Magento_SwaggerWebapi' => 1, + 'Magento_SwaggerWebapiAsync' => 1, + 'Magento_Swatches' => 1, + 'Magento_SwatchesGraphQl' => 1, + 'Magento_SwatchesLayeredNavigation' => 1, + 'Magento_Tax' => 1, + 'Magento_TaxGraphQl' => 1, + 'Magento_TaxImportExport' => 1, + 'Magento_TwoFactorAuth' => 1, + 'Magento_ThemeGraphQl' => 1, + 'Magento_Translation' => 1, + 'Magento_AdminAdobeImsTwoFactorAuth' => 1, + 'Magento_GoogleOptimizer' => 1, + 'Magento_Ups' => 1, + 'Magento_SampleData' => 1, + 'Magento_CatalogUrlRewriteGraphQl' => 1, + 'Magento_AsynchronousOperations' => 1, + 'Magento_Usps' => 1, + 'Magento_InventoryConfigurableProductFrontendUi' => 1, + 'Magento_PaypalCaptcha' => 1, + 'Magento_VaultGraphQl' => 1, + 'Magento_Version' => 1, + 'Magento_InventoryInStorePickupWebapiExtension' => 1, + 'Magento_WebapiAsync' => 1, + 'Magento_WebapiSecurity' => 1, + 'Magento_Weee' => 1, + 'Magento_WeeeGraphQl' => 1, + 'Magento_CurrencySymbol' => 1, + 'Magento_Wishlist' => 1, + 'Magento_WishlistAnalytics' => 1, + 'Magento_WishlistGraphQl' => 1, + 'PayPal_Braintree' => 1, + 'PayPal_BraintreeGraphQl' => 1, + 'Temando_ShippingRemover' => 1 + ] +]; diff --git a/test-resources/workspace/app/etc/db_schema.xml b/test-resources/workspace/app/etc/db_schema.xml new file mode 100644 index 0000000..d7af909 --- /dev/null +++ b/test-resources/workspace/app/etc/db_schema.xml @@ -0,0 +1,17 @@ + + + + + + + + + +
+
diff --git a/test-resources/workspace/app/etc/di.xml b/test-resources/workspace/app/etc/di.xml new file mode 100644 index 0000000..6056a54 --- /dev/null +++ b/test-resources/workspace/app/etc/di.xml @@ -0,0 +1,1980 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system/currency/installed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Magento\Framework\Acl\Builder\Proxy + + + + + Magento\Framework\Filesystem\Driver\File + + + + + Magento\Framework\Filesystem\Driver\File + + + + + + Magento\Framework\Communication\Config\Reader\XmlReader\Converter + Magento\Framework\Communication\Config\Reader\XmlReader\SchemaLocator + communication.xml + + name + name + + + + + + + + Magento\WebapiAsync\Code\Generator\Config\RemoteServiceReader\Communication + 0 + + + Magento\Framework\Communication\Config\Reader\XmlReader + 10 + + + Magento\Framework\Communication\Config\Reader\EnvReader + 20 + + + Magento\Framework\MessageQueue\Code\Generator\Config\RemoteServiceReader\Communication + 5 + + + + + + + main + + Magento\Framework\Logger\Handler\System + Magento\Framework\Logger\Handler\Debug + Magento\Framework\Logger\Handler\Syslog + + + + + + Magento + + + + + Magento\Framework\Model\ActionValidator\RemoveAction\Proxy + + + + + + + + + + Magento\Framework\Message\Session\Proxy + Magento\Framework\Message\ExceptionMessageLookupFactory + + + + + + Magento\Backend\App\Request\PathInfoProcessor\Proxy + Magento\Framework\App\Route\ConfigInterface\Proxy + + + + + Magento\Framework\Session\Config\ConfigInterface\Proxy + + + + + + + Magento\Framework\Session\SaveHandler\DbTable + Magento\Framework\Session\SaveHandler\Redis + + + + + + + Magento\Framework\App\Feed + + + + + + Cm\RedisSession\Handler\ConfigInterface + Cm\RedisSession\Handler\LoggerInterface + + + + + global + + + + + adminhtml + + + + + Magento\Framework\App\State::PARAM_MODE + + + + + Magento\Framework\App\State::PARAM_MODE + + + + + Magento\Framework\App\State::PARAM_MODE + + + + + Magento\Framework\App\State::PARAM_MODE + + + + + Magento\Framework\App\Cache\Frontend\Factory::PARAM_CACHE_FORCED_OPTIONS + + + Magento\Framework\Cache\Frontend\Decorator\TagScope + + MAGE + + + + Magento\Framework\Cache\Frontend\Decorator\Logger + + + Magento\Framework\App\ResourceConnection\Proxy + + + + + Magento\Backend\Setup\ConfigOptionsList::CONFIG_PATH_BACKEND_FRONTNAME + + + + + Magento\Framework\App\Cache\State::PARAM_BAN_CACHE + + + + + Magento\Store\Model\StoreManager::PARAM_RUN_CODE + Magento\Store\Model\StoreManager::PARAM_RUN_TYPE + + + + + Magento\Framework\App\Cache\Type\Translate + Magento\Framework\Locale\Resolver\Proxy + Magento\Framework\Translate\ResourceInterface\Proxy + Magento\Framework\App\Request\Http\Proxy + + + + + Magento\Framework\Translate\InlineInterface\Proxy + + + + + + + Magento\Store\Model\StoreManagerInterface\Proxy + + + + + + Magento\Framework\App\Cache\Type\Config + Magento\Framework\ObjectManager\Config\Reader\Dom\Proxy + + + + + Magento\Framework\App\Cache\Type\Config + + + + + config_cache + Magento\Framework\Cache\Config\Reader\Proxy + + + + + Magento\Framework\App\Cache\Type\Config + Magento\Framework\ObjectManager\Config\Reader\Dom\Proxy + interception + + + + + Magento\Framework\App\Cache\Type\Config + + + + + Magento\Framework\App\Cache\Type\Config + Magento\Framework\ObjectManager\Config\Reader\Dom\Proxy + plugin-list + + primary + global + + + + + + Magento\Framework\ObjectManager\Config\Reader\Dom\Proxy + \Psr\Log\LoggerInterface\Proxy + + primary + global + + + + + + Magento\Framework\App\ResourceConnection\ConnectionFactory + + + + + Magento\Framework\App\ResourceConnection\Config\Reader\Proxy + Magento\Framework\App\Cache\Type\Config\Proxy + + + + + Magento\Framework\App\Config\FileResolver\Proxy + + + + + primary + Magento\Framework\App\AreaList\Proxy + + + + + Magento\Framework\Session\Generic\Proxy + Magento\Store\Model\ScopeInterface::SCOPE_STORE + + + + + + Magento\Framework\View\Layout\Argument\Interpreter\Options + layoutArrayArgumentReaderInterpreterProxy + Magento\Framework\Data\Argument\Interpreter\Boolean + Magento\Framework\Data\Argument\Interpreter\Number + Magento\Framework\Data\Argument\Interpreter\StringUtils + Magento\Framework\Data\Argument\Interpreter\NullType + Magento\Framework\View\Layout\Argument\Interpreter\Passthrough + Magento\Framework\View\Layout\Argument\Interpreter\Passthrough + Magento\Framework\View\Layout\Argument\Interpreter\Passthrough + + Magento\Framework\View\Model\Layout\Merge::TYPE_ATTRIBUTE + + + + + + Magento\Framework\View\Layout\Argument\Interpreter\Options + layoutArrayArgumentGeneratorInterpreterProxy + Magento\Framework\Data\Argument\Interpreter\Boolean + Magento\Framework\Data\Argument\Interpreter\Number + Magento\Framework\Data\Argument\Interpreter\StringUtils + Magento\Framework\Data\Argument\Interpreter\NullType + layoutObjectArgumentInterpreter + Magento\Framework\View\Layout\Argument\Interpreter\Url + Magento\Framework\View\Layout\Argument\Interpreter\HelperMethod + + Magento\Framework\View\Model\Layout\Merge::TYPE_ATTRIBUTE + + + + + layoutArgumentGeneratorInterpreterInternal + + + + + layoutArgumentReaderInterpreter + + + + + layoutArgumentGeneratorInterpreterInternal + + + + + + layoutArrayArgumentReaderInterpreter + + + + + layoutArrayArgumentGeneratorInterpreter + + + + + Magento\Framework\View\Element\Block\ArgumentInterface + + + + + Magento\Framework\Data\Argument\Interpreter\StringUtils + + + + + + Magento\Framework\View\Layout\Reader\Container + Magento\Framework\View\Layout\Reader\Block + Magento\Framework\View\Layout\Reader\UiComponent + + + + + + containerRenderPool + + + + + + Magento\Framework\View\Layout\Reader\Container + Magento\Framework\View\Layout\Reader\Block + Magento\Framework\View\Layout\Reader\Move + Magento\Framework\View\Layout\Reader\UiComponent + + + + + + blockRenderPool + Magento\Store\Model\ScopeInterface::SCOPE_STORE + layoutArgumentReaderInterpreter + + + + + blockRenderPool + + + + + Magento\Store\Model\ScopeInterface::SCOPE_STORE + + + + + + Magento\Framework\View\Layout\Reader\Container + Magento\Framework\View\Layout\Reader\Block + Magento\Framework\View\Layout\Reader\Move + Magento\Framework\View\Layout\Reader\UiComponent + + + + + + bodyRenderPool + + + + + + Magento\Framework\View\Page\Config\Reader\Html + Magento\Framework\View\Page\Config\Reader\Head + Magento\Framework\View\Page\Config\Reader\Body + Magento\Framework\View\Layout\Reader\Container + Magento\Framework\View\Layout\Reader\Block + Magento\Framework\View\Layout\Reader\Move + Magento\Framework\View\Layout\Reader\UiComponent + + + + + + commonRenderPool + Magento\Framework\App\Cache\Type\Layout + + + + + + Magento\Framework\View\Layout\Reader\Container + Magento\Framework\View\Layout\Reader\Block + Magento\Framework\View\Layout\Reader\Move + Magento\Framework\View\Layout\Reader\UiComponent + + + + + + genericLayoutRenderPool + + + + + + Magento\Framework\View\Page\Config\Reader\Html + Magento\Framework\View\Page\Config\Reader\Head + Magento\Framework\View\Page\Config\Reader\Body + + + + + + + Magento\Framework\View\Page\Config\Generator\Head + Magento\Framework\View\Page\Config\Generator\Body + Magento\Framework\View\Layout\Generator\Block + Magento\Framework\View\Layout\Generator\Container + Magento\Framework\View\Layout\Generator\UiComponent + + + + + + + Magento\Framework\View\Page\Config\Generator\Head + Magento\Framework\View\Page\Config\Generator\Body + Magento\Framework\View\Layout\Generator\Block + Magento\Framework\View\Layout\Generator\Container + Magento\Framework\View\Layout\Generator\UiComponent + + + + + + pageConfigRenderPool + pageLayoutGeneratorPool + Magento_Theme::root.phtml + + + + + layoutArgumentGeneratorInterpreter + + + + + + Magento\Framework\Data\OptionSourceInterface + Magento\Framework\View\Element\UiComponent\DataProvider\DataProviderInterface + + + Magento\Framework\Model\ResourceModel\AbstractResource + + + + + + Magento\Indexer\Model\Mview\View\State + Magento\Framework\Mview\View\Changelog + + + + + Magento\Framework\Mview\Config\Data\Proxy + + + + + Magento\Framework\Mview\View\State\CollectionInterface + + + + + + + AlternativeSourceProcessors + + + + + + Magento\MediaStorage\Model\File\Storage\Response + developerPublisher + + + + + Magento\Framework\View\Asset\PreProcessor\MinificationFilenameResolver + alternative-source-css + Magento\Framework\View\Asset\LockerProcess + + + Magento\Framework\Css\PreProcessor\Adapter\Less\Processor + + + + + + + developerMaterialization + + + + + + Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink + Magento\Framework\App\View\Asset\MaterializationStrategy\Copy + + + + + + Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Simple + + + + + Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Simple + + + + + Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Simple + + + + + + viewFileFallbackResolver + + + + + + viewFileMinifiedFallbackResolver + + + + + + \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceFactoryGenerator + \Magento\Framework\ObjectManager\Code\Generator\Factory + \Magento\Framework\ObjectManager\Code\Generator\Proxy + \Magento\Framework\Interception\Code\Generator\Interceptor + \Magento\Framework\ObjectManager\Profiler\Code\Generator\Logger + \Magento\Framework\Api\Code\Generator\Mapper + \Magento\Framework\ObjectManager\Code\Generator\Persistor + \Magento\Framework\ObjectManager\Code\Generator\Repository + \Magento\Framework\ObjectManager\Code\Generator\Converter + \Magento\Framework\Api\Code\Generator\SearchResults + \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator + \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator + \Magento\Framework\MessageQueue\Code\Generator\RemoteServiceGenerator + \Magento\Framework\Async\Code\Generator\ProxyDeferredGenerator + + + + + + + + + page_cache + + + + + + + + + page_cache + + + + + + Magento\Framework\Translate\Inline\ParserInterface\Proxy + + + + + + + + Magento\Framework\Search\Dynamic\Algorithm\Auto + Magento\Framework\Search\Dynamic\Algorithm\Manual + Magento\Framework\Search\Dynamic\Algorithm\Improved + + + + + + Magento\Framework\View\Layout\File\Collector\Aggregated\Proxy + pageLayoutFileCollectorAggregated + Magento\Framework\App\Cache\Type\Layout + Magento\Framework\View\Layout\LayoutCacheKeyInterface + + + + + false + + + + + + core + index + index + + + + + + Magento\Framework\App\Cache\Type\Collection + collection_ + 86400 + + + + + Magento\Framework\Event\Config\Reader\Proxy + + + + + + layout + + + + + layoutFileSourceBase + + + + + layoutFileSourceBaseFiltered + + + + + + layout + + + + + layoutFileSourceTheme + + + + + layoutFileSourceThemeFiltered + + + + + + layout/override/base + + + + + layoutFileSourceOverrideBase + + + + + layoutFileSourceOverrideBaseFiltered + + + + + + layout/override/theme + + + + + layoutFileSourceOverrideTheme + + + + + layoutFileSourceOverrideThemeFiltered + + + + + layoutFileSourceBaseSorted + layoutFileSourceThemeSorted + layoutFileSourceOverrideBaseSorted + layoutFileSourceOverrideThemeSorted + + + + + page_layout + + + + + pageLayoutFileSourceBase + + + + + pageLayoutFileSourceBaseFiltered + + + + + page_layout + + + + + pageLayoutFileSourceTheme + + + + + pageLayoutFileSourceThemeFiltered + + + + + + page_layout/override/base + + + + + pageLayoutFileSourceOverrideBase + + + + + pageLayoutFileSourceOverrideBaseFiltered + + + + + + page_layout/override/theme + + + + + pageLayoutFileSourceOverrideTheme + + + + + pageLayoutFileSourceOverrideThemeFiltered + + + + + + pageLayoutFileSourceBaseSorted + pageLayoutFileSourceThemeSorted + pageLayoutFileSourceOverrideBaseSorted + pageLayoutFileSourceOverrideThemeSorted + + + + + + + pageFileSourceBase + + + + + pageFileSourceBaseFiltered + + + + + + + pageFileSourceTheme + + + + + pageFileSourceThemeFiltered + + + + + + page/override + + + + + pageFileSourceOverrideBase + + + + + pageFileSourceOverrideBaseFiltered + + + + + + override/theme + + + + + pageFileSourceOverrideTheme + + + + + pageFileSourceOverrideThemeFiltered + + + + + + Magento\Framework\View\Layout\Reader\Container + Magento\Framework\View\Layout\Reader\Move + + + + + + pageLayoutFileCollectorAggregated + pageLayoutRenderPool + + + + + pageFileSourceBaseSorted + pageFileSourceThemeSorted + pageFileSourceOverrideBaseSorted + pageFileSourceOverrideThemeSorted + + + + + Magento\Framework\View\Design\Theme\Image\Uploader\Proxy + + + + + Magento\Framework\App\Config\Initial\Reader\Proxy + + + + + Magento\Framework\App\Config\Initial\Converter + + + + + Magento\Framework\App\Route\Config\Reader\Proxy + + + + + Magento\Store\Model\ScopeInterface::SCOPE_STORE + + Shockwave Flash + + + + + + + Magento\Framework\DataObject\Copy\Config\Data\Proxy + + + + + fieldset.xml + Magento\Framework\DataObject\Copy\Config\SchemaLocator + + + + + urn:magento:framework:DataObject/etc/fieldset.xsd + urn:magento:framework:DataObject/etc/fieldset_file.xsd + + + + + Magento\Framework\DataObject\Copy\Config\Reader\Proxy + fieldset_config + + + + + Magento\Framework\Image\Adapter\Gd2 + + + + + page_types.xml + Magento\Framework\View\Layout\PageType\Config\Converter + Magento\Framework\View\Layout\PageType\Config\SchemaLocator + frontend + + + + + Magento\Framework\View\Layout\PageType\Config\Reader + page_types_config + + + + + Magento\Framework\View\Layout\PageType\Config\Data + + + + + message + + + + + Magento\Framework\Message\Session\Storage + + + + + frontend + + + + + + Magento\Framework\Filesystem\Driver\File + + + + + + [a-z]+[_a-z\d]*?\/[a-z]+[_a-z\d]*?)::.*?$/sui]]> + [a-z]+[_a-z\d]*?\/[a-z]+[_a-z\d]*?)\".*?}}/sui]]> + [a-z]+[_a-z\d]*?\/[a-z]+[_a-z\d]*?)\".*?>/sui]]> + s:\d+:"(?P[a-z]+[_a-z\d]*?/[a-z]+[_a-z\d]*?)")#sui]]> + + + + + + + + application/json + Magento\Framework\Webapi\Rest\Request\Deserializer\Json + + + application/xml + Magento\Framework\Webapi\Rest\Request\Deserializer\Xml + + + application/xhtml+xml + Magento\Framework\Webapi\Rest\Request\Deserializer\Xml + + + text/xml + Magento\Framework\Webapi\Rest\Request\Deserializer\Xml + + + + + + + Magento\Framework\App\Cache\Type\Config + + + + + + Magento\Framework\Reflection\ExtensionAttributesProcessor\Proxy + Magento\Framework\Reflection\CustomAttributesProcessor\Proxy + + + + + Magento\Framework\UrlInterface + + + + + + + view.xml + Magento\Framework\Config\Converter + Magento\Framework\Config\SchemaLocator + Magento\Framework\Config\FileResolver + + + + + Magento\Framework\DB\Select\RendererProxy + + + + + Magento\Framework\Locale\ResolverInterface + + + + + + + Magento\Framework\DB\Select\DistinctRenderer + 100 + distinct + + + Magento\Framework\DB\Select\ColumnsRenderer + 200 + columns + + + Magento\Framework\DB\Select\UnionRenderer + 300 + union + + + Magento\Framework\DB\Select\FromRenderer + 400 + from + + + Magento\Framework\DB\Select\WhereRenderer + 500 + where + + + Magento\Framework\DB\Select\GroupRenderer + 600 + group + + + Magento\Framework\DB\Select\HavingRenderer + 700 + having + + + Magento\Framework\DB\Select\OrderRenderer + 800 + order + + + Magento\Framework\DB\Select\LimitRenderer + 900 + limitcount + + + Magento\Framework\DB\Select\ForUpdateRenderer + 1000 + forupdate + + + + + + + + + Magento\Framework\EntityManager\Operation\CheckIfExists + Magento\Framework\EntityManager\Operation\Read + Magento\Framework\EntityManager\Operation\Create + Magento\Framework\EntityManager\Operation\Update + Magento\Framework\EntityManager\Operation\Delete + + + + + + + + Magento\Framework\App\Cache\Type\Block::TYPE_IDENTIFIER + Magento\Framework\App\Cache\Type\Collection::TYPE_IDENTIFIER + + + + + + + Magento\Framework\EntityManager\Mapper + + + + + + + + Magento\Framework\Api\SearchCriteria\CollectionProcessor\FilterProcessor + Magento\Framework\Api\SearchCriteria\CollectionProcessor\SortingProcessor + Magento\Framework\Api\SearchCriteria\CollectionProcessor\PaginationProcessor + + + + + + + Magento\Framework\DB\Select\InQueryModifier + Magento\Framework\DB\Select\LikeQueryModifier + Magento\Framework\DB\Select\CompositeQueryModifier + + + + + + + HASH + BTREE + + + INNODB + MEMORY + MYISAM + + + + + + Magento\Framework\DB\FieldDataConverter::BATCH_SIZE_VARIABLE_NAME + + + + + + + true + + + + + + + Magento\Framework\View\Asset\PreProcessor\Passthrough + + + + + Magento\Framework\App\Filesystem\DirectoryList::STATIC_VIEW + deployed_version.txt + + + + + Magento\Directory\Helper\Data::XML_PATH_DEFAULT_LOCALE + Magento\Framework\App\ScopeInterface::SCOPE_DEFAULT + + + + + + Magento\Framework\View\Element\Message\Renderer\EscapeRenderer + Magento\Framework\View\Element\Message\Renderer\BlockRenderer + + + + + + + + \Magento\Framework\View\Element\Message\Renderer\EscapeRenderer::CODE + + + + + + + Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_OUTPUT + Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_LOG_EVERYTHING + Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_QUERY_TIME_THRESHOLD + Magento\Framework\Config\ConfigOptionsListConstants::CONFIG_PATH_DB_LOGGER_INCLUDE_STACKTRACE + + + + + Magento\Config\App\Config\Source\EnvironmentConfigSource + + + + + Magento\Framework\Message\ExceptionMessageFactory + + + + + + updated_at + + + + + + + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Table + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Real + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Real + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Real + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Integer + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Integer + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Integer + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Integer + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Date + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Timestamp + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Timestamp + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\LongText + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\MediumText + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Text + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Blob + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\MediumBlob + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\LongBlob + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Boolean + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Unique + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Primary + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Foreign + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Index + \Magento\Framework\Setup\Declaration\Schema\Dto\Factories\Json + + + + + + + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Boolean + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Integer + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Integer + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Integer + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Integer + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Real + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Real + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Real + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Blob + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Blob + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Blob + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Blob + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Blob + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Blob + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Timestamp + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Date + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Timestamp + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\StringBinary + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Columns\Json + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Index + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Constraints\Internal + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Constraints\Internal + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Constraints\Internal + \Magento\Framework\Setup\Declaration\Schema\Db\MySQL\Definition\Constraints\ForeignKey + + + + + + + Magento\Framework\Setup\Declaration\Schema\Db\MySQL\DDL\Triggers\MigrateDataFrom + + + + + + + Magento\Framework\Setup\Declaration\Schema\FileSystem\XmlReader + + + + + + true + + + + + false + + + + + urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd + + + + + Magento\Framework\Config\FileResolverByModule + Magento\Framework\Setup\Declaration\Schema\Config\Converter + Magento\Framework\Setup\Declaration\Schema\Config\SchemaLocator + db_schema.xml + + name + name + referenceId + referenceId + name + name + + + + + + + Magento\Framework\Setup\Declaration\Schema\Operations\ReCreateTable + Magento\Framework\Setup\Declaration\Schema\Operations\CreateTable + Magento\Framework\Setup\Declaration\Schema\Operations\DropTable + Magento\Framework\Setup\Declaration\Schema\Operations\DropReference + Magento\Framework\Setup\Declaration\Schema\Operations\ModifyColumn + Magento\Framework\Setup\Declaration\Schema\Operations\AddColumn + Magento\Framework\Setup\Declaration\Schema\Operations\DropElement + Magento\Framework\Setup\Declaration\Schema\Operations\AddComplexElement + Magento\Framework\Setup\Declaration\Schema\Operations\ModifyTable + + + Magento\Framework\Setup\Declaration\Schema\DataSavior\TableSavior + Magento\Framework\Setup\Declaration\Schema\DataSavior\ColumnSavior + + + + + + + default + + + + + + + Magento\Framework\Setup\Declaration\Schema\Declaration\ValidationRules\CheckReferenceColumnHasIndex + Magento\Framework\Setup\Declaration\Schema\Declaration\ValidationRules\RealTypes + Magento\Framework\Setup\Declaration\Schema\Declaration\ValidationRules\PrimaryKeyCanBeCreated + Magento\Framework\Setup\Declaration\Schema\Declaration\ValidationRules\IncosistentReferenceDefinition + Magento\Framework\Setup\Declaration\Schema\Declaration\ValidationRules\AutoIncrementColumnValidation + + + + + + + Magento\Framework\Setup\SchemaListenerDefinition\IntegerDefinition + Magento\Framework\Setup\SchemaListenerDefinition\IntegerDefinition + Magento\Framework\Setup\SchemaListenerDefinition\IntegerDefinition + Magento\Framework\Setup\SchemaListenerDefinition\IntegerDefinition + Magento\Framework\Setup\SchemaListenerDefinition\IntegerDefinition + Magento\Framework\Setup\SchemaListenerDefinition\RealDefinition + Magento\Framework\Setup\SchemaListenerDefinition\RealDefinition + Magento\Framework\Setup\SchemaListenerDefinition\RealDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TextBlobDefinition + Magento\Framework\Setup\SchemaListenerDefinition\CharDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TimestampDefinition + Magento\Framework\Setup\SchemaListenerDefinition\TimestampDefinition + Magento\Framework\Setup\SchemaListenerDefinition\DateDefinition + Magento\Framework\Setup\SchemaListenerDefinition\BooleanDefinition + Magento\Framework\Setup\SchemaListenerDefinition\JsonDefinition + + + + + + schema + + + + + data + + + + + \Magento\Framework\Setup\Patch\DataPatchReader + \Magento\Framework\Setup\Patch\SchemaPatchReader + + + + + \Magento\Framework\Setup\Patch\DataPatchReader + + + + + \Magento\Framework\Setup\Patch\SchemaPatchReader + + + + + + + Magento\Framework\MessageQueue\Config\Reader\Xml + 10 + + + Magento\Framework\MessageQueue\Config\Reader\Env + 20 + + + + + + + + + Magento\Framework\MessageQueue\Config\Reader\Xml\Converter\TopicConfig + 20 + + + + + + + Magento\Framework\MessageQueue\Consumer\Config\CompositeReader + + + + + + Magento\Framework\MessageQueue\Consumer\Config\Xml\Reader + Magento\Framework\MessageQueue\Consumer\Config\Env\Reader + + + + + + + Magento\Framework\MessageQueue\Consumer\Config\Validator\RequiredFields + Magento\Framework\MessageQueue\Consumer\Config\Validator\FieldsTypes + Magento\Framework\MessageQueue\Consumer\Config\Validator\Handlers + Magento\Framework\MessageQueue\Consumer\Config\Validator\ConsumerInstance + + + + + + + Magento\Framework\MessageQueue\Publisher\Config\Validator\Format + Magento\Framework\MessageQueue\Publisher\Config\Validator\EnabledConnection + + + + + + + Magento\WebapiAsync\Code\Generator\Config\RemoteServiceReader\Publisher + Magento\Framework\MessageQueue\Publisher\Config\RemoteService\Reader + Magento\Framework\MessageQueue\Publisher\Config\Xml\Reader + Magento\Framework\MessageQueue\Publisher\Config\Env\Reader + + + + + + + Magento\Framework\MessageQueue\Topology\Config\Validator\Format + Magento\Framework\MessageQueue\Topology\Config\Validator\FieldsTypes + Magento\Framework\MessageQueue\Topology\Config\Validator\DependentFields + + + + + + + Magento\Framework\MessageQueue\Topology\Config\RemoteService\Reader + Magento\Framework\MessageQueue\Topology\Config\Xml\Reader + + + + + + + Magento\Framework\Amqp\Topology\BindingInstallerType\Queue + Magento\Framework\Amqp\Topology\BindingInstallerType\Exchange + + + + + + + magento + magento + + + + + + + amqp + db + + + + + + + Magento\Framework\Setup\Declaration\Schema\Db\MySQL\DDL\Triggers\MigrateDataFromAnotherTable + + + + + + + + Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT + + + + + Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT + + + + + + + CsrfRequestValidator + + Magento\Framework\App\Request\HttpMethodValidator + + + + + + + + + \Magento\Framework\App\Action\HttpOptionsActionInterface + \Magento\Framework\App\Action\HttpGetActionInterface + \Magento\Framework\App\Action\HttpGetActionInterface + \Magento\Framework\App\Action\HttpPostActionInterface + \Magento\Framework\App\Action\HttpPutActionInterface + \Magento\Framework\App\Action\HttpPatchActionInterface + \Magento\Framework\App\Action\HttpDeleteActionInterface + \Magento\Framework\App\Action\HttpConnectActionInterface + \Magento\Framework\App\Action\HttpPropfindActionInterface + \Magento\Framework\App\Action\HttpTraceActionInterface + + + + + + + Magento\Framework\App\ScopeResolver + + + + + + Magento\Framework\Lock\Backend\Database + + + + + + Magento\Framework\App\Cache\RuntimeStaleCacheStateModifier + + + + + + + + + + + + + + + + + + + block_html + + + + + configured_block_cache + + + + + + ^8\.0\. + ^5\.7\. + ^10\.[2-6]\. + + + + + + + div + a + p + span + em + strong + ul + li + ol + h5 + h4 + h3 + h2 + h1 + table + tbody + tr + td + th + tfoot + img + hr + figure + button + i + u + br + b + + + class + width + height + style + alt + title + border + id + + + + href + + + src + + + type + + + + Magento\Framework\Validator\HTML\StyleAttributeValidator + + + + + + + + Magento\Framework\View\Helper\SecureHtmlRenderer\Proxy + Magento\Framework\Escaper + Magento\Framework\Locale\LocaleFormatter + + + + + + + admin + soap + rest + graphql + standard + + + + + + + + Magento\Framework\Webapi\Validator\EntityArrayValidator + Magento\Framework\Webapi\Validator\SearchCriteriaValidator + + + + + + + + 999999 + + + + + 300 + + + + + + + Magento\Framework\GraphQl\Query\Resolver\Argument\Validator\SearchCriteriaValidator + + + + + + 300 + + + + + 999999 + + + + diff --git a/tsconfig.json b/tsconfig.json index 289dd18..89a4164 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,5 +12,6 @@ "emitDecoratorMetadata": true, "experimentalDecorators": true, "strict": true - } + }, + "include": ["src"] }